From ccac2c1cf89cb91a20a2b209b4df9fc1e655b4a9 Mon Sep 17 00:00:00 2001 From: Andreas Svanberg <andreass@dsv.su.se> Date: Wed, 6 Nov 2024 11:23:28 +0100 Subject: [PATCH 1/8] Enable creating an API using Spring Web (#5) SciPro will have to provide information to the upcoming student portal. Wicket does not have the ability to serve JSON in the usual REST way and is only able to serve HTML. The most common way to write JSON over HTTP API:s in Java is using Spring Web, but currently SciPro uses Guice for dependency injection rather than Spring which makes adding Spring Web a bit more tricky. This pull request attempts to solve this by doing the following; * Replacing Guice with Spring * Adding a new API module that uses Spring Web * Turning the entire system into a standard Spring Boot web application The hope is that these changes will bring the following benefits; * Harmonize our web stack (Daisy uses Spring and the new lecture hall system is full Spring Boot) * Enable easy development of a traditional JSON over HTTP API * Ease future recruitment by using the most common Java web frameworks Reviewed-on: https://gitea.dsv.su.se/DMC/scipro/pulls/5 Reviewed-by: niat8586 <nico@dsv.su.se> Co-authored-by: Andreas Svanberg <andreass@dsv.su.se> Co-committed-by: Andreas Svanberg <andreass@dsv.su.se> --- .gitignore | 2 + GetToken.java | 101 ++ README.md | 13 + api/pom.xml | 25 + .../se/su/dsv/scipro/api/ApiController.java | 29 + core/pom.xml | 28 +- core/src/main/java/modules/CoreModule.java | 160 --- core/src/main/java/modules/ProfileModule.java | 15 - .../main/java/modules/RepositoryModule.java | 66 -- .../java/se/su/dsv/scipro/CoreConfig.java | 1012 +++++++++++++++++ .../se/su/dsv/scipro/DataInitializer.java | 2 +- .../dsv/scipro/RepositoryConfiguration.java | 285 +++++ .../activityplan/ActivityPlanFacadeImpl.java | 2 +- .../checklist/ChecklistAnswerServiceImpl.java | 2 +- .../checklist/ChecklistCategoryRepo.java | 2 +- .../checklist/ChecklistQuestionRepo.java | 2 +- .../checklist/ChecklistServiceImpl.java | 2 +- .../ChecklistTemplateServiceImpl.java | 2 +- .../daisyExternal/DaisyExternalModule.java | 20 - .../se/su/dsv/scipro/events/EventModule.java | 15 - .../dsv/scipro/file/FileDescriptionRepo.java | 2 +- .../se/su/dsv/scipro/file/FileModule.java | 16 - .../scipro/file/FileReferenceRepository.java | 2 +- .../file/FileReferenceRepositoryImpl.java | 6 +- .../su/dsv/scipro/file/FileServiceImpl.java | 2 +- .../scipro/file/ProjectFileServiceImpl.java | 2 +- .../FinalSeminarOppositionRepo.java | 2 +- .../FinalSeminarRepositoryImpl.java | 4 +- .../finalseminar/FinalSeminarServiceImpl.java | 2 +- .../FinalSeminarSettingsServiceImpl.java | 2 +- .../FinalSeminarUploadControllerImpl.java | 2 +- .../finalthesis/FinalThesisServiceImpl.java | 2 +- .../firstmeeting/FirstMeetingModule.java | 11 - .../scipro/forum/BasicForumServiceImpl.java | 2 +- .../se/su/dsv/scipro/forum/ForumModule.java | 26 - .../forum/ForumPostReadStateRepository.java | 2 +- .../ForumPostReadStateRepositoryImpl.java | 2 +- .../dsv/scipro/forum/ForumPostRepository.java | 2 +- .../scipro/forum/GroupForumServiceImpl.java | 2 +- .../scipro/forum/GroupThreadRepository.java | 2 +- .../scipro/forum/ProjectForumServiceImpl.java | 2 +- .../scipro/forum/ProjectThreadRepository.java | 2 +- .../notifications/ForumNotifications.java | 2 +- .../ForumNotificationsModule.java | 11 - .../se/su/dsv/scipro/gdpr/GDPRModule.java | 12 - .../GeneralSystemSettingsServiceImpl.java | 2 +- .../GradingHistoryEventRepositoryImpl.java | 2 +- .../su/dsv/scipro/grading/GradingModule.java | 37 - ...NationalSubjectCategoryRepositoryImpl.java | 2 +- .../PublicationMetadataRepository.java | 2 +- .../PublicationMetadataRepositoryImpl.java | 6 +- .../PublicationMetadataServiceImpl.java | 4 +- .../ActivityFinalSeminarModule.java | 11 - .../ActivityFinalSeminarRepository.java | 2 +- .../activityforum/ActivityForumModule.java | 11 - .../se/su/dsv/scipro/mail/PrintingMailer.java | 2 +- .../match/AllowAllIdeaCreationJudge.java | 2 +- .../match/ApplicationPeriodServiceImpl.java | 2 +- .../scipro/match/FirstMeetingRepository.java | 2 +- .../su/dsv/scipro/match/IdeaServiceImpl.java | 2 +- .../dsv/scipro/match/KeywordServiceImpl.java | 2 +- .../se/su/dsv/scipro/match/MatchModule.java | 26 - .../dsv/scipro/match/ProgramServiceImpl.java | 2 +- .../MilestoneActivityTemplateRepository.java | 2 +- .../MilestonePhaseTemplateServiceImpl.java | 2 +- .../NotificationControllerImpl.java | 3 +- .../notifications/NotificationModule.java | 28 - .../NotificationServiceImpl.java | 2 +- .../impl/NotificationMailFormatterImpl.java | 3 +- .../DeliveryConfigurationServiceImpl.java | 2 +- .../ReceiverConfigurationServiceImpl.java | 2 +- .../se/su/dsv/scipro/oauth/OAuthModule.java | 25 - .../se/su/dsv/scipro/oauth/OAuthSettings.java | 2 +- .../dsv/scipro/peer/CommentServiceImpl.java | 2 +- .../su/dsv/scipro/peer/CommentThreadRepo.java | 2 +- .../scipro/peer/CommentThreadServiceImpl.java | 2 +- .../se/su/dsv/scipro/peer/PeerModule.java | 13 - .../se/su/dsv/scipro/peer/PeerPortalImpl.java | 4 +- .../scipro/peer/PeerRequestRepository.java | 2 +- .../scipro/peer/PeerRequestServiceImpl.java | 2 +- .../plagiarism/PlagiarismControlImpl.java | 2 +- .../scipro/plagiarism/PlagiarismModule.java | 11 - .../plagiarism/urkund/UrkundApiImpl.java | 2 +- .../plagiarism/urkund/UrkundModule.java | 26 - .../plagiarism/urkund/UrkundServiceImpl.java | 2 +- .../dsv/scipro/profiles/CurrentProfile.java | 6 +- .../ProjectPeopleStatisticsServiceImpl.java | 2 +- .../se/su/dsv/scipro/project/ProjectRepo.java | 2 +- .../dsv/scipro/project/ProjectRepoImpl.java | 2 +- .../scipro/project/ProjectServiceImpl.java | 2 +- .../ProjectPartnerRepositoryImpl.java | 2 +- .../ProjectPartnerServiceImpl.java | 2 +- .../scipro/reflection/ReflectionModule.java | 13 - .../reflection/ReflectionServiceImpl.java | 6 +- .../report/GradingReportServiceImpl.java | 3 +- .../report/GradingReportTemplateRepoImpl.java | 2 +- .../report/OppositionReportServiceImpl.java | 2 +- .../dsv/scipro/report/ReportServiceImpl.java | 2 +- .../FinalSeminarApprovalServiceImpl.java | 2 +- ...jectFinalSeminarStatisticsServiceImpl.java | 2 +- .../ReviewerCapacityServiceImpl.java | 6 +- .../ReviewerDeadlineSettingsRepository.java | 2 +- ...eviewerDeadlineSettingsRepositoryImpl.java | 4 +- .../ReviewerDeadlineSettingsServiceImpl.java | 2 +- .../ReviewerInteractionServiceImpl.java | 2 +- .../ReviewerTargetRepositoryImpl.java | 2 +- .../dsv/scipro/reviewing/ReviewingModule.java | 25 - .../RoughDraftApprovalServiceImpl.java | 2 +- .../security/auth/AuthenticationModule.java | 15 - .../serviceimpls/UserProfileServiceImpl.java | 3 +- .../se/su/dsv/scipro/sukat/SukatModule.java | 10 - .../se/su/dsv/scipro/survey/SurveyModule.java | 17 - .../dsv/scipro/survey/SurveyServiceImpl.java | 2 +- .../scipro/system/AbstractServiceImpl.java | 2 +- .../dsv/scipro/system/FooterAddressRepo.java | 2 +- .../su/dsv/scipro/system/FooterLinkRepo.java | 2 +- .../scipro/system/FooterLinkServiceImpl.java | 2 +- .../se/su/dsv/scipro/system/GenericRepo.java | 2 +- .../dsv/scipro/system/MergeServiceImpl.java | 2 +- .../se/su/dsv/scipro/system/PasswordRepo.java | 2 +- .../se/su/dsv/scipro/system/UserRepo.java | 2 +- .../dsv/scipro/war/PluginConfiguration.java | 4 + .../scipro/workerthreads/AbstractWorker.java | 33 +- .../scipro/workerthreads/WorkerModule.java | 31 - .../WorkerTransactionManager.java | 20 + .../su/dsv/scipro/forum/ForumModuleTest.java | 23 +- .../scipro/group/GroupServiceImplTest.java | 270 ++--- .../su/dsv/scipro/match/MatchModuleTest.java | 31 +- .../NotificationControllerImplTest.java | 3 +- .../urkund/UrkundSettingsRepositoryTest.java | 23 +- .../UrkundSubmissionRepositoryTest.java | 23 +- .../scipro/reviewing/ReviewingModuleTest.java | 12 - .../reviewing/ReviewingServiceImplTest.java | 322 +++--- .../java/se/su/dsv/scipro/test/GuiceTest.java | 73 -- .../su/dsv/scipro/test/IntegrationTest.java | 54 +- .../se/su/dsv/scipro/test/SpringTest.java | 92 ++ daisy-integration/pom.xml | 4 +- .../impl/ExternalImporterDaisyImpl.java | 2 +- .../impl/ImporterTransactionsImpl.java | 2 +- .../daisy/DaisyIntegrationConfiguration.java | 182 +++ .../scipro/integration/daisy/DaisyModule.java | 44 - .../dsv/scipro/io/facade/ExporterFacade.java | 2 +- .../services/com.google.inject.Module | 1 - .../se.su.dsv.scipro.war.PluginConfiguration | 1 + ...radingCompletedMilestoneActivatorTest.java | 15 +- .../daisy/workers/ProjectExporterTest.java | 13 +- .../daisy/workers/ProjectFinalizerTest.java | 14 +- docker-compose.yml | 15 + pom.xml | 30 +- view/pom.xml | 25 +- view/src/main/java/ApplicationBootstrap.java | 68 -- view/src/main/java/DatabaseMigration.java | 35 - .../se/su/dsv/scipro/FileSystemStore.java | 2 +- .../se/su/dsv/scipro/SciProApplication.java | 3 +- .../java/se/su/dsv/scipro/SciProModule.java | 33 - .../AdminCreateProjectConfirmationPage.java | 2 +- .../panels/AdminEditFooterAddressPanel.java | 2 +- .../crosscutting/CrosscuttingModule.java | 17 - .../match/SupervisorIdeaDetailsPage.java | 2 +- .../peer/PeerReviewFilterDetailsPanel.java | 2 +- .../peer/PeerReviewStatusStatisticsPanel.java | 2 +- .../panels/SupervisorApprovalPanel.java | 2 +- .../services/com.google.inject.Module | 15 - view/src/main/webapp/WEB-INF/web.xml | 28 - .../java/se/su/dsv/scipro/SciProTest.java | 31 +- war/pom.xml | 109 ++ .../java/se/su/dsv/scipro/war/ApiConfig.java | 72 ++ .../java/se/su/dsv/scipro/war/MailConfig.java | 48 +- .../main/java/se/su/dsv/scipro/war/Main.java | 168 +++ .../war/SpringManagedWorkerTransactions.java | 50 + .../dsv/scipro/war/WicketConfiguration.java | 90 ++ .../se/su/dsv/scipro/war/WorkerConfig.java | 245 ++++ .../scipro/workerthreads/SchedulerImpl.java | 23 +- .../scipro/workerthreads/TaskScheduling.java | 0 ...akarta.servlet.ServletContainerInitializer | 1 + war/src/main/resources/application.properties | 20 + war/src/main/webapp/WEB-INF/web.xml | 14 + .../workerthreads/SchedulerImplTest.java | 8 +- 178 files changed, 3104 insertions(+), 1677 deletions(-) create mode 100644 GetToken.java create mode 100644 README.md create mode 100644 api/pom.xml create mode 100644 api/src/main/java/se/su/dsv/scipro/api/ApiController.java delete mode 100644 core/src/main/java/modules/CoreModule.java delete mode 100644 core/src/main/java/modules/ProfileModule.java delete mode 100644 core/src/main/java/modules/RepositoryModule.java create mode 100644 core/src/main/java/se/su/dsv/scipro/CoreConfig.java create mode 100644 core/src/main/java/se/su/dsv/scipro/RepositoryConfiguration.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/daisyExternal/DaisyExternalModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/events/EventModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/file/FileModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/firstmeeting/FirstMeetingModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/forum/ForumModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/forum/notifications/ForumNotificationsModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/gdpr/GDPRModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/grading/GradingModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/integration/activityfinalseminar/ActivityFinalSeminarModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/integration/activityforum/ActivityForumModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/match/MatchModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/notifications/NotificationModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/oauth/OAuthModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/peer/PeerModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/plagiarism/PlagiarismModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/reflection/ReflectionModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/reviewing/ReviewingModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/security/auth/AuthenticationModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/sukat/SukatModule.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/survey/SurveyModule.java create mode 100644 core/src/main/java/se/su/dsv/scipro/war/PluginConfiguration.java delete mode 100644 core/src/main/java/se/su/dsv/scipro/workerthreads/WorkerModule.java create mode 100644 core/src/main/java/se/su/dsv/scipro/workerthreads/WorkerTransactionManager.java delete mode 100644 core/src/test/java/se/su/dsv/scipro/test/GuiceTest.java create mode 100644 core/src/test/java/se/su/dsv/scipro/test/SpringTest.java create mode 100644 daisy-integration/src/main/java/se/su/dsv/scipro/integration/daisy/DaisyIntegrationConfiguration.java delete mode 100644 daisy-integration/src/main/java/se/su/dsv/scipro/integration/daisy/DaisyModule.java delete mode 100644 daisy-integration/src/main/resources/META-INF/services/com.google.inject.Module create mode 100644 daisy-integration/src/main/resources/META-INF/services/se.su.dsv.scipro.war.PluginConfiguration create mode 100644 docker-compose.yml delete mode 100644 view/src/main/java/ApplicationBootstrap.java delete mode 100644 view/src/main/java/DatabaseMigration.java delete mode 100644 view/src/main/java/se/su/dsv/scipro/SciProModule.java delete mode 100644 view/src/main/java/se/su/dsv/scipro/crosscutting/CrosscuttingModule.java delete mode 100644 view/src/main/resources/META-INF/services/com.google.inject.Module delete mode 100755 view/src/main/webapp/WEB-INF/web.xml create mode 100644 war/pom.xml create mode 100644 war/src/main/java/se/su/dsv/scipro/war/ApiConfig.java rename core/src/main/java/se/su/dsv/scipro/mail/MailModule.java => war/src/main/java/se/su/dsv/scipro/war/MailConfig.java (52%) create mode 100644 war/src/main/java/se/su/dsv/scipro/war/Main.java create mode 100644 war/src/main/java/se/su/dsv/scipro/war/SpringManagedWorkerTransactions.java create mode 100644 war/src/main/java/se/su/dsv/scipro/war/WicketConfiguration.java create mode 100644 war/src/main/java/se/su/dsv/scipro/war/WorkerConfig.java rename {core => war}/src/main/java/se/su/dsv/scipro/workerthreads/SchedulerImpl.java (63%) rename {core => war}/src/main/java/se/su/dsv/scipro/workerthreads/TaskScheduling.java (100%) create mode 100644 war/src/main/resources/META-INF/services/jakarta.servlet.ServletContainerInitializer create mode 100644 war/src/main/resources/application.properties create mode 100755 war/src/main/webapp/WEB-INF/web.xml rename {core => war}/src/test/java/se/su/dsv/scipro/workerthreads/SchedulerImplTest.java (83%) diff --git a/.gitignore b/.gitignore index 40f55760b0..204ca95f52 100755 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,5 @@ view/target *.log fitnesse/target/ daisy-integration/target/ +war/target/ +api/target/ diff --git a/GetToken.java b/GetToken.java new file mode 100644 index 0000000000..68c0dee549 --- /dev/null +++ b/GetToken.java @@ -0,0 +1,101 @@ +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpServer; + +import java.awt.Toolkit; +import java.awt.datatransfer.StringSelection; +import java.io.IOException; +import java.io.OutputStream; +import java.net.Authenticator; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class GetToken { + public static void main(String[] args) throws IOException { + URI baseUri = URI.create("http://localhost:59733"); + String clientId = "get-token"; + String clientSecret = "get-token-secret"; + + System.out.println("Browse to " + baseUri.resolve("authorize?response_type=code&client_id=" + clientId)); + + HttpClient httpClient = HttpClient.newBuilder() + .authenticator(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(clientId, clientSecret.toCharArray()); + } + }) + .build(); + + HttpServer httpServer = HttpServer.create(); + httpServer.bind(new InetSocketAddress(59732), 0); + + Thread thread = Thread.currentThread(); + + httpServer.createContext("/", exchange -> { + exchange.sendResponseHeaders(200, 0); + try (OutputStream responseBody = exchange.getResponseBody()) { + responseBody.write("All done, close tab".getBytes(StandardCharsets.UTF_8)); + } + + Map<String, List<String>> queryParams = getQueryParams(exchange); + String code = queryParams.get("code").get(0); + HttpRequest httpRequest = HttpRequest.newBuilder() + .uri(baseUri.resolve("exchange")) + .header("Content-Type", "application/x-www-form-urlencoded") + .POST(HttpRequest.BodyPublishers.ofString("grant_type=authorization_code&code=" + code)) + .build(); + try { + HttpResponse<String> response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + System.out.println(response.body()); + + // Try to copy the access token to the clipboard + Matcher matcher = Pattern.compile("access_token\":\"([^\"]+)\"") + .matcher(response.body()); + if (matcher.find()) { + StringSelection clipboardData = new StringSelection(matcher.group(1)); + Toolkit.getDefaultToolkit() + .getSystemClipboard() + .setContents(clipboardData, clipboardData); + try { Thread.sleep(1_000L); } catch (InterruptedException e) { } + System.out.println("Access token copied to clipboard (probably)"); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + thread.interrupt(); + } + }); + + httpServer.start(); + try { + Thread.sleep(Duration.ofMinutes(1L).toMillis()); + System.out.println("No authorization within one minute, exiting."); + System.exit(1); + } catch (InterruptedException ignored) { + // expected + } + httpServer.stop(0); + } + + private static Map<String, List<String>> getQueryParams(final HttpExchange exchange) { + String query = exchange.getRequestURI() + .getQuery(); + return Arrays.stream(query.split("&")) + .map(s -> s.split("=")) + .collect(Collectors.groupingBy( + split -> split[0], + Collectors.mapping(split -> split[1], Collectors.toList()))); + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000000..749d07cb72 --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +## Working with the API +The API is protected by OAuth 2 acting as a [resource server](https://www.oauth.com/oauth2-servers/the-resource-server/) +verifying tokens using [token introspection](https://datatracker.ietf.org/doc/html/rfc7662). + +When developing it uses a locally running instance of an +[authorization server](https://datatracker.ietf.org/doc/html/rfc6749#section-1.1) +that is run inside [Docker](https://www.docker.com). It can be started with `docker compose -f docker-compose.yml up`. +Since there is no frontend to interact with the authorization server there's a helper script in +[GetToken.java](GetToken.java) that can be run directly with `java GetToken.java` to run through the authorization flow +and get an access token. + +Once the token has been obtained go to the [Swagger UI](http://localhost:8080/api/swagger) to interact with the API. +Click the "Authorize" button in the top right and paste the access token to log in. diff --git a/api/pom.xml b/api/pom.xml new file mode 100644 index 0000000000..35c607e1b1 --- /dev/null +++ b/api/pom.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>se.su.dsv.scipro</groupId> + <artifactId>SciPro</artifactId> + <version>0.1-SNAPSHOT</version> + </parent> + + <artifactId>api</artifactId> + + <dependencies> + <dependency> + <groupId>se.su.dsv.scipro</groupId> + <artifactId>core</artifactId> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-webmvc</artifactId> + </dependency> + </dependencies> + +</project> \ No newline at end of file diff --git a/api/src/main/java/se/su/dsv/scipro/api/ApiController.java b/api/src/main/java/se/su/dsv/scipro/api/ApiController.java new file mode 100644 index 0000000000..8059cdde66 --- /dev/null +++ b/api/src/main/java/se/su/dsv/scipro/api/ApiController.java @@ -0,0 +1,29 @@ +package se.su.dsv.scipro.api; + +import jakarta.inject.Inject; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import se.su.dsv.scipro.system.User; +import se.su.dsv.scipro.system.UserService; + +import java.util.Optional; + +@RestController +public class ApiController { + private final UserService userService; + + @Inject + public ApiController(UserService userService) { + this.userService = userService; + } + + @GetMapping("/hello-world") + public String helloWorld(@RequestParam(value = "username", required = false) String username) { + String name = Optional.ofNullable(username) + .map(userService::findByUsername) + .map(User::getFullName) + .orElse("World"); + return "Hello, " + name + "!"; + } +} diff --git a/core/pom.xml b/core/pom.xml index df548c1fad..a3c2a1a1e9 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -12,14 +12,6 @@ <artifactId>core</artifactId> <dependencies> - <dependency> - <groupId>com.google.inject</groupId> - <artifactId>guice</artifactId> - </dependency> - <dependency> - <groupId>com.google.inject.extensions</groupId> - <artifactId>guice-persist</artifactId> - </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> @@ -62,12 +54,9 @@ <groupId>org.glassfish.jersey.inject</groupId> <artifactId>jersey-hk2</artifactId> </dependency> - - <!--Database stuff--> <dependency> - <groupId>org.hsqldb</groupId> - <artifactId>hsqldb</artifactId> - <scope>test</scope> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> </dependency> <!--QueryDSL--> @@ -87,10 +76,19 @@ <groupId>jakarta.persistence</groupId> <artifactId>jakarta.persistence-api</artifactId> </dependency> + <dependency> + <groupId>jakarta.transaction</groupId> + <artifactId>jakarta.transaction-api</artifactId> + </dependency> <dependency> <groupId>org.hibernate.orm</groupId> <artifactId>hibernate-core</artifactId> - <scope>runtime</scope> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hsqldb</groupId> + <artifactId>hsqldb</artifactId> + <scope>test</scope> </dependency> <!--Additional stuff--> @@ -130,8 +128,6 @@ <version>4.0.5</version> <scope>runtime</scope> </dependency> - - </dependencies> <build> diff --git a/core/src/main/java/modules/CoreModule.java b/core/src/main/java/modules/CoreModule.java deleted file mode 100644 index 075c6e9ed8..0000000000 --- a/core/src/main/java/modules/CoreModule.java +++ /dev/null @@ -1,160 +0,0 @@ -package modules; - -import com.google.inject.AbstractModule; -import com.google.inject.multibindings.Multibinder; -import com.google.inject.multibindings.OptionalBinder; -import se.su.dsv.scipro.activityplan.*; -import se.su.dsv.scipro.checklist.*; -import se.su.dsv.scipro.date.DateService; -import se.su.dsv.scipro.date.DateServiceImpl; -import se.su.dsv.scipro.events.EventModule; -import se.su.dsv.scipro.finalseminar.*; -import se.su.dsv.scipro.finalthesis.FinalThesisService; -import se.su.dsv.scipro.finalthesis.FinalThesisServiceImpl; -import se.su.dsv.scipro.finalthesis.PublishingConsentService; -import se.su.dsv.scipro.finalthesis.PublishingConsentUnavailable; -import se.su.dsv.scipro.firstmeeting.FirstMeetingService; -import se.su.dsv.scipro.firstmeeting.FirstMeetingServiceImpl; -import se.su.dsv.scipro.forum.ForumModule; -import se.su.dsv.scipro.generalsystemsettings.GeneralSystemSettingsService; -import se.su.dsv.scipro.generalsystemsettings.GeneralSystemSettingsServiceImpl; -import se.su.dsv.scipro.group.GroupFacade; -import se.su.dsv.scipro.group.GroupFacadeImpl; -import se.su.dsv.scipro.group.GroupService; -import se.su.dsv.scipro.group.GroupServiceImpl; -import se.su.dsv.scipro.integration.activityfinalseminar.ActivityFinalSeminarRepository; -import se.su.dsv.scipro.integration.activityfinalseminar.ActivityFinalSeminarRepositoryImpl; -import se.su.dsv.scipro.integration.activityforum.ActivityThreadRepository; -import se.su.dsv.scipro.integration.activityforum.ActivityThreadRepositoryImpl; -import se.su.dsv.scipro.mail.MailModule; -import se.su.dsv.scipro.match.ApplicationPeriodFacade; -import se.su.dsv.scipro.match.ApplicationPeriodFacadeImpl; -import se.su.dsv.scipro.match.MatchModule; -import se.su.dsv.scipro.milestones.service.*; -import se.su.dsv.scipro.milestones.service.impl.MilestoneActivityTemplateServiceImpl; -import se.su.dsv.scipro.milestones.service.impl.MilestonePhaseTemplateServiceImpl; -import se.su.dsv.scipro.milestones.service.impl.MilestoneServiceImpl; -import se.su.dsv.scipro.milestones.service.impl.MilestoneStatisticsServiceImpl; -import se.su.dsv.scipro.misc.DaysService; -import se.su.dsv.scipro.misc.DaysServiceImpl; -import se.su.dsv.scipro.nonworkperiod.NonWorkDayPeriodService; -import se.su.dsv.scipro.nonworkperiod.NonWorkDayPeriodServiceImpl; -import se.su.dsv.scipro.notes.NoteService; -import se.su.dsv.scipro.notes.NoteServiceImpl; -import se.su.dsv.scipro.notifications.NotificationModule; -import se.su.dsv.scipro.notifications.settings.service.DeliveryConfigurationService; -import se.su.dsv.scipro.notifications.settings.service.DeliveryConfigurationServiceImpl; -import se.su.dsv.scipro.notifications.settings.service.ReceiverConfigurationService; -import se.su.dsv.scipro.notifications.settings.service.ReceiverConfigurationServiceImpl; -import se.su.dsv.scipro.peer.*; -import se.su.dsv.scipro.plagiarism.*; -import se.su.dsv.scipro.project.ProjectNoteService; -import se.su.dsv.scipro.project.ProjectPeopleStatisticsService; -import se.su.dsv.scipro.project.ProjectPeopleStatisticsServiceImpl; -import se.su.dsv.scipro.project.ProjectService; -import se.su.dsv.scipro.project.ProjectServiceImpl; -import se.su.dsv.scipro.projectpartner.ProjectPartnerRepository; -import se.su.dsv.scipro.projectpartner.ProjectPartnerRepositoryImpl; -import se.su.dsv.scipro.projectpartner.ProjectPartnerService; -import se.su.dsv.scipro.projectpartner.ProjectPartnerServiceImpl; -import se.su.dsv.scipro.reflection.ReflectionModule; -import se.su.dsv.scipro.report.*; -import se.su.dsv.scipro.reviewing.ProjectFinalSeminarStatisticsService; -import se.su.dsv.scipro.reviewing.ProjectFinalSeminarStatisticsServiceImpl; -import se.su.dsv.scipro.springdata.serviceimpls.SupervisorServiceImpl; -import se.su.dsv.scipro.springdata.serviceimpls.UnitServiceImpl; -import se.su.dsv.scipro.springdata.serviceimpls.UserProfileServiceImpl; -import se.su.dsv.scipro.springdata.services.SupervisorService; -import se.su.dsv.scipro.springdata.services.UnitService; -import se.su.dsv.scipro.springdata.services.UserProfileService; -import se.su.dsv.scipro.system.*; -import se.su.dsv.scipro.thesislink.ExternalLinkService; -import se.su.dsv.scipro.thesislink.ExternalLinkServiceImpl; - -public class CoreModule extends AbstractModule { - @Override - protected void configure() { - install(new RepositoryModule()); - bind(FooterLinkService.class).to(FooterLinkServiceImpl.class); - bind(ActivityThreadRepository.class).to(ActivityThreadRepositoryImpl.class); - bind(ActivityFinalSeminarRepository.class).to(ActivityFinalSeminarRepositoryImpl.class); - bind(UserService.class).to(UserServiceImpl.class); - bind(MergeService.class).to(MergeServiceImpl.class); - bind(PasswordService.class).to(PasswordServiceImpl.class); - bind(GeneralSystemSettingsService.class).to(GeneralSystemSettingsServiceImpl.class); - bind(ProjectTypeService.class).to(ProjectTypeServiceImpl.class); - bind(UnitService.class).to(UnitServiceImpl.class); - bind(ResearchAreaService.class).to(ResearchAreaServiceImpl.class); - bind(DateService.class).to(DateServiceImpl.class); - bind(ActivityPlanFacade.class).to(ActivityPlanFacadeImpl.class); - bind(ProjectService.class).to(ProjectServiceImpl.class); - bind(ProjectFinalSeminarStatisticsService.class).to(ProjectFinalSeminarStatisticsServiceImpl.class); - bind(ProjectPeopleStatisticsService.class).to(ProjectPeopleStatisticsServiceImpl.class); - bind(DeliveryConfigurationService.class).to(DeliveryConfigurationServiceImpl.class); - bind(ReceiverConfigurationService.class).to(ReceiverConfigurationServiceImpl.class); - bind(ActivityService.class).to(ActivityServiceImpl.class); - bind(ActivityPlanService.class).to(ActivityPlanServiceImpl.class); - bind(ActivityPlanTemplateService.class).to(ActivityPlanTemplateServiceImpl.class); - bind(ChecklistService.class).to(ChecklistServiceImpl.class); - bind(UserProfileService.class).to(UserProfileServiceImpl.class); - bind(FinalSeminarService.class).to(FinalSeminarServiceImpl.class); - bind(FinalSeminarSettingsService.class).to(FinalSeminarSettingsServiceImpl.class); - bind(SupervisorService.class).to(SupervisorServiceImpl.class); - bind(DaysService.class).to(DaysServiceImpl.class); - bind(NonWorkDayPeriodService.class).to(NonWorkDayPeriodServiceImpl.class); - bind(FinalSeminarOppositionService.class).to(FinalSeminarOppositionServiceImpl.class); - bind(AuthorRepository.class).to(AuthorRepositoryImpl.class); - bind(OppositionReportService.class).to(OppositionReportServiceImpl.class); - bind(ApplicationPeriodFacade.class).to(ApplicationPeriodFacadeImpl.class); - bind(GroupFacade.class).to(GroupFacadeImpl.class); - bind(ExternalLinkService.class).to(ExternalLinkServiceImpl.class); - bind(PeerRequestService.class).to(PeerRequestServiceImpl.class); - bind(PeerReviewService.class).to(PeerReviewServiceImpl.class); - bind(MilestoneActivityTemplateService.class).to(MilestoneActivityTemplateServiceImpl.class); - bind(FinalThesisService.class).to(FinalThesisServiceImpl.class); - OptionalBinder.newOptionalBinder(binder(), PublishingConsentService.class) - .setDefault().to(PublishingConsentUnavailable.class); - bind(ChecklistTemplateService.class).to(ChecklistTemplateServiceImpl.class); - bind(PeerPortal.class).to(PeerPortalImpl.class); - bind(FinalSeminarRespondentService.class).to(FinalSeminarRespondentServiceImpl.class); - bind(ProjectPartnerService.class).to(ProjectPartnerServiceImpl.class); - bind(GradingReportService.class).to(GradingReportServiceImpl.class); - bind(GradeCalculatorService.class).to(GradeCalculatorServiceImpl.class); - bind(UserNameService.class).to(UserNameServiceImpl.class); - bind(MileStoneService.class).to(MilestoneServiceImpl.class); - bind(MilestoneStatisticsService.class).to(MilestoneStatisticsServiceImpl.class); - bind(MilestonePhaseTemplateService.class).to(MilestonePhaseTemplateServiceImpl.class); - bind(ReportService.class).to(ReportServiceImpl.class); - bind(CommentThreadService.class).to(CommentThreadServiceImpl.class); - bind(CommentService.class).to(CommentServiceImpl.class); - bind(PerformReviewService.class).to(PeerPortalImpl.class); - bind(EventService.class).to(EventServiceImpl.class); - bind(ChecklistAnswerService.class).to(ChecklistAnswerServiceImpl.class); - bind(FinalSeminarUploadController.class).to(FinalSeminarUploadControllerImpl.class); - bind(FinalSeminarActiveParticipationService.class).to(FinalSeminarActiveParticipationServiceImpl.class); - bind(ExternalResourceService.class).to(ExternalResourceServiceImpl.class); - bind(GroupService.class).to(GroupServiceImpl.class); - bind(NoteService.class).to(NoteServiceImpl.class); - bind(MilestoneActivator.class).asEagerSingleton(); - bind(ActivateCompletedMilestonesOnNewProjects.class).asEagerSingleton(); - bind(FirstMeetingService.class).to(FirstMeetingServiceImpl.class); - bind(FinalSeminarCreationSubscribers.class).asEagerSingleton(); - bind(ProjectPartnerRepository.class).to(ProjectPartnerRepositoryImpl.class); - bind(ProjectNoteService.class).to(ProjectServiceImpl.class); - - install(new PlagiarismModule()); - install(new NotificationModule()); - install(new ProfileModule()); - install(new EventModule()); - install(new MatchModule()); - install(new MailModule()); - install(new ForumModule()); - install(new ReflectionModule()); - - Multibinder.newSetBinder(binder(), UserImportService.class); - bind(UserSearchService.class).to(AggregateUserSearch.class); - Multibinder.newSetBinder(binder(), UserSearchProvider.class) - .addBinding().to(LocalUserSearch.class); - - } -} diff --git a/core/src/main/java/modules/ProfileModule.java b/core/src/main/java/modules/ProfileModule.java deleted file mode 100644 index 16d276dba8..0000000000 --- a/core/src/main/java/modules/ProfileModule.java +++ /dev/null @@ -1,15 +0,0 @@ -package modules; - -import com.google.inject.Key; -import com.google.inject.PrivateModule; -import com.google.inject.name.Names; -import se.su.dsv.scipro.profiles.CurrentProfile; - -public class ProfileModule extends PrivateModule { - @Override - protected void configure() { - requireBinding(Key.get(String.class, Names.named("profile"))); - bind(CurrentProfile.class).asEagerSingleton(); - expose(CurrentProfile.class); - } -} diff --git a/core/src/main/java/modules/RepositoryModule.java b/core/src/main/java/modules/RepositoryModule.java deleted file mode 100644 index 2ae13bc0cb..0000000000 --- a/core/src/main/java/modules/RepositoryModule.java +++ /dev/null @@ -1,66 +0,0 @@ -package modules; - -import com.google.inject.AbstractModule; -import se.su.dsv.scipro.checklist.ChecklistCategoryRepo; -import se.su.dsv.scipro.checklist.ChecklistCategoryRepoImpl; -import se.su.dsv.scipro.checklist.ChecklistQuestionRepo; -import se.su.dsv.scipro.checklist.ChecklistQuestionRepoImpl; -import se.su.dsv.scipro.finalseminar.FinalSeminarActiveParticipationRepository; -import se.su.dsv.scipro.finalseminar.FinalSeminarActiveParticipationRepositoryImpl; -import se.su.dsv.scipro.finalseminar.FinalSeminarOppositionRepo; -import se.su.dsv.scipro.finalseminar.FinalSeminarOppositionRepoImpl; -import se.su.dsv.scipro.finalseminar.FinalSeminarRepository; -import se.su.dsv.scipro.finalseminar.FinalSeminarRepositoryImpl; -import se.su.dsv.scipro.milestones.MilestoneActivityTemplateRepository; -import se.su.dsv.scipro.milestones.MilestoneActivityTemplateRepositoryImpl; -import se.su.dsv.scipro.peer.CommentThreadRepo; -import se.su.dsv.scipro.peer.CommentThreadRepoImpl; -import se.su.dsv.scipro.peer.PeerRequestRepository; -import se.su.dsv.scipro.peer.PeerRequestRepositoryImpl; -import se.su.dsv.scipro.peer.PeerReviewRepository; -import se.su.dsv.scipro.peer.PeerReviewRepositoryImpl; -import se.su.dsv.scipro.project.ProjectRepo; -import se.su.dsv.scipro.project.ProjectRepoImpl; -import se.su.dsv.scipro.report.GradingReportTemplateRepo; -import se.su.dsv.scipro.report.GradingReportTemplateRepoImpl; -import se.su.dsv.scipro.report.OppositionReportRepo; -import se.su.dsv.scipro.report.OppositionReportRepoImpl; -import se.su.dsv.scipro.report.SupervisorGradingReportRepository; -import se.su.dsv.scipro.report.SupervisorGradingReportRepositoryImpl; -import se.su.dsv.scipro.reviewing.DecisionRepository; -import se.su.dsv.scipro.reviewing.DecisionRepositoryImpl; -import se.su.dsv.scipro.reviewing.ReviewerTargetRepository; -import se.su.dsv.scipro.reviewing.ReviewerTargetRepositoryImpl; -import se.su.dsv.scipro.system.FooterAddressRepo; -import se.su.dsv.scipro.system.FooterAddressRepoImpl; -import se.su.dsv.scipro.system.FooterLinkRepo; -import se.su.dsv.scipro.system.FooterLinkRepoImpl; -import se.su.dsv.scipro.system.PasswordRepo; -import se.su.dsv.scipro.system.PasswordRepoImpl; -import se.su.dsv.scipro.system.UserRepo; -import se.su.dsv.scipro.system.UserRepoImpl; - -public class RepositoryModule extends AbstractModule { - @Override - protected void configure() { - bind(ChecklistQuestionRepo.class).to(ChecklistQuestionRepoImpl.class); - bind(FinalSeminarOppositionRepo.class).to(FinalSeminarOppositionRepoImpl.class); - bind(FinalSeminarActiveParticipationRepository.class).to(FinalSeminarActiveParticipationRepositoryImpl.class); - bind(GradingReportTemplateRepo.class).to(GradingReportTemplateRepoImpl.class); - bind(MilestoneActivityTemplateRepository.class).to(MilestoneActivityTemplateRepositoryImpl.class); - bind(OppositionReportRepo.class).to(OppositionReportRepoImpl.class); - bind(PasswordRepo.class).to(PasswordRepoImpl.class); - bind(ProjectRepo.class).to(ProjectRepoImpl.class); - bind(UserRepo.class).to(UserRepoImpl.class); - bind(PeerReviewRepository.class).to(PeerReviewRepositoryImpl.class); - bind(PeerRequestRepository.class).to(PeerRequestRepositoryImpl.class); - bind(ChecklistCategoryRepo.class).to(ChecklistCategoryRepoImpl.class); - bind(CommentThreadRepo.class).to(CommentThreadRepoImpl.class); - bind(FooterLinkRepo.class).to(FooterLinkRepoImpl.class); - bind(FooterAddressRepo.class).to(FooterAddressRepoImpl.class); - bind(FinalSeminarRepository.class).to(FinalSeminarRepositoryImpl.class); - bind(ReviewerTargetRepository.class).to(ReviewerTargetRepositoryImpl.class); - bind(DecisionRepository.class).to(DecisionRepositoryImpl.class); - bind(SupervisorGradingReportRepository.class).to(SupervisorGradingReportRepositoryImpl.class); - } -} \ No newline at end of file diff --git a/core/src/main/java/se/su/dsv/scipro/CoreConfig.java b/core/src/main/java/se/su/dsv/scipro/CoreConfig.java new file mode 100644 index 0000000000..d9245d2155 --- /dev/null +++ b/core/src/main/java/se/su/dsv/scipro/CoreConfig.java @@ -0,0 +1,1012 @@ +package se.su.dsv.scipro; + +import com.google.common.eventbus.EventBus; +import jakarta.inject.Provider; +import jakarta.persistence.EntityManager; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import se.su.dsv.scipro.activityplan.ActivityPlanFacade; +import se.su.dsv.scipro.activityplan.ActivityPlanFacadeImpl; +import se.su.dsv.scipro.activityplan.ActivityPlanServiceImpl; +import se.su.dsv.scipro.activityplan.ActivityPlanTemplateServiceImpl; +import se.su.dsv.scipro.activityplan.ActivityServiceImpl; +import se.su.dsv.scipro.checklist.ChecklistAnswerServiceImpl; +import se.su.dsv.scipro.checklist.ChecklistServiceImpl; +import se.su.dsv.scipro.checklist.ChecklistTemplateService; +import se.su.dsv.scipro.checklist.ChecklistTemplateServiceImpl; +import se.su.dsv.scipro.daisyExternal.http.DaisyAPIImpl; +import se.su.dsv.scipro.date.DateServiceImpl; +import se.su.dsv.scipro.file.FileDescriptionRepo; +import se.su.dsv.scipro.file.FileReferenceRepository; +import se.su.dsv.scipro.file.FileService; +import se.su.dsv.scipro.file.FileServiceImpl; +import se.su.dsv.scipro.file.FileStore; +import se.su.dsv.scipro.file.ProjectFileRepository; +import se.su.dsv.scipro.file.ProjectFileService; +import se.su.dsv.scipro.file.ProjectFileServiceImpl; +import se.su.dsv.scipro.finalseminar.AuthorRepository; +import se.su.dsv.scipro.finalseminar.FinalSeminarActiveParticipationRepository; +import se.su.dsv.scipro.finalseminar.FinalSeminarActiveParticipationServiceImpl; +import se.su.dsv.scipro.finalseminar.FinalSeminarCreationSubscribers; +import se.su.dsv.scipro.finalseminar.FinalSeminarOppositionRepo; +import se.su.dsv.scipro.finalseminar.FinalSeminarOppositionServiceImpl; +import se.su.dsv.scipro.finalseminar.FinalSeminarRepository; +import se.su.dsv.scipro.finalseminar.FinalSeminarRespondentServiceImpl; +import se.su.dsv.scipro.finalseminar.FinalSeminarService; +import se.su.dsv.scipro.finalseminar.FinalSeminarServiceImpl; +import se.su.dsv.scipro.finalseminar.FinalSeminarSettingsService; +import se.su.dsv.scipro.finalseminar.FinalSeminarSettingsServiceImpl; +import se.su.dsv.scipro.finalseminar.FinalSeminarUploadControllerImpl; +import se.su.dsv.scipro.finalthesis.FinalThesisService; +import se.su.dsv.scipro.finalthesis.FinalThesisServiceImpl; +import se.su.dsv.scipro.firstmeeting.FirstMeetingServiceImpl; +import se.su.dsv.scipro.forum.AbstractThreadRepository; +import se.su.dsv.scipro.forum.BasicForumService; +import se.su.dsv.scipro.forum.BasicForumServiceImpl; +import se.su.dsv.scipro.forum.ForumPostReadStateRepository; +import se.su.dsv.scipro.forum.ForumPostRepository; +import se.su.dsv.scipro.forum.GroupForumService; +import se.su.dsv.scipro.forum.GroupForumServiceImpl; +import se.su.dsv.scipro.forum.GroupThreadRepository; +import se.su.dsv.scipro.forum.ProjectForumService; +import se.su.dsv.scipro.forum.ProjectForumServiceImpl; +import se.su.dsv.scipro.forum.ProjectThreadRepository; +import se.su.dsv.scipro.forum.notifications.ForumNotificationRepository; +import se.su.dsv.scipro.forum.notifications.ForumNotifications; +import se.su.dsv.scipro.gdpr.ZipReporter; +import se.su.dsv.scipro.generalsystemsettings.GeneralSystemSettingsService; +import se.su.dsv.scipro.generalsystemsettings.GeneralSystemSettingsServiceImpl; +import se.su.dsv.scipro.grading.GradingHistory; +import se.su.dsv.scipro.grading.GradingHistoryEventRepository; +import se.su.dsv.scipro.grading.GradingServiceImpl; +import se.su.dsv.scipro.grading.NationalSubjectCategoryRepository; +import se.su.dsv.scipro.grading.NationalSubjectCategoryServiceImpl; +import se.su.dsv.scipro.grading.PublicationMetadataRepository; +import se.su.dsv.scipro.grading.PublicationMetadataServiceImpl; +import se.su.dsv.scipro.grading.ThesisSubmissionHistoryService; +import se.su.dsv.scipro.group.GroupService; +import se.su.dsv.scipro.group.GroupServiceImpl; +import se.su.dsv.scipro.integration.activityfinalseminar.ActivityFinalSeminarRepository; +import se.su.dsv.scipro.integration.activityfinalseminar.FinalSeminarActivityHandler; +import se.su.dsv.scipro.integration.activityforum.ActivityThreadRepository; +import se.su.dsv.scipro.integration.activityforum.PostActivityUploadToForum; +import se.su.dsv.scipro.mail.MailEventService; +import se.su.dsv.scipro.mail.MailEventServiceImpl; +import se.su.dsv.scipro.match.AddActivityPlanOnProjectStart; +import se.su.dsv.scipro.match.ApplicationPeriodFacadeImpl; +import se.su.dsv.scipro.match.ApplicationPeriodProjectTypeServiceImpl; +import se.su.dsv.scipro.match.ApplicationPeriodService; +import se.su.dsv.scipro.match.ApplicationPeriodServiceImpl; +import se.su.dsv.scipro.match.FirstMeetingRepository; +import se.su.dsv.scipro.match.IdeaRepository; +import se.su.dsv.scipro.match.IdeaService; +import se.su.dsv.scipro.match.IdeaServiceImpl; +import se.su.dsv.scipro.match.KeywordServiceImpl; +import se.su.dsv.scipro.match.MatchFollowUpServiceImpl; +import se.su.dsv.scipro.match.MatchServiceImpl; +import se.su.dsv.scipro.match.PreliminaryMatchServiceImpl; +import se.su.dsv.scipro.match.ProgramServiceImpl; +import se.su.dsv.scipro.match.ProjectStartNotifier; +import se.su.dsv.scipro.match.TargetRepository; +import se.su.dsv.scipro.match.TargetServiceImpl; +import se.su.dsv.scipro.milestones.MilestoneActivityTemplateRepository; +import se.su.dsv.scipro.milestones.service.ActivateCompletedMilestonesOnNewProjects; +import se.su.dsv.scipro.milestones.service.MilestoneActivityTemplateService; +import se.su.dsv.scipro.milestones.service.impl.MilestoneActivityTemplateServiceImpl; +import se.su.dsv.scipro.milestones.service.impl.MilestonePhaseTemplateServiceImpl; +import se.su.dsv.scipro.milestones.service.impl.MilestoneServiceImpl; +import se.su.dsv.scipro.milestones.service.impl.MilestoneStatisticsServiceImpl; +import se.su.dsv.scipro.misc.DaysService; +import se.su.dsv.scipro.misc.DaysServiceImpl; +import se.su.dsv.scipro.nonworkperiod.NonWorkDayPeriodService; +import se.su.dsv.scipro.nonworkperiod.NonWorkDayPeriodServiceImpl; +import se.su.dsv.scipro.notes.NoteServiceImpl; +import se.su.dsv.scipro.notifications.NotificationController; +import se.su.dsv.scipro.notifications.NotificationControllerImpl; +import se.su.dsv.scipro.notifications.NotificationEventRepository; +import se.su.dsv.scipro.notifications.NotificationEventServiceImpl; +import se.su.dsv.scipro.notifications.NotificationService; +import se.su.dsv.scipro.notifications.NotificationServiceImpl; +import se.su.dsv.scipro.notifications.Notifications; +import se.su.dsv.scipro.notifications.interfaces.NotificationMailFormatter; +import se.su.dsv.scipro.notifications.interfaces.impl.NotificationMailFormatterImpl; +import se.su.dsv.scipro.notifications.settings.service.DeliveryConfigurationService; +import se.su.dsv.scipro.notifications.settings.service.DeliveryConfigurationServiceImpl; +import se.su.dsv.scipro.notifications.settings.service.ReceiverConfigurationService; +import se.su.dsv.scipro.notifications.settings.service.ReceiverConfigurationServiceImpl; +import se.su.dsv.scipro.oauth.OAuthServiceImpl; +import se.su.dsv.scipro.oauth.OAuthSettings; +import se.su.dsv.scipro.peer.CommentServiceImpl; +import se.su.dsv.scipro.peer.CommentThreadRepo; +import se.su.dsv.scipro.peer.CommentThreadServiceImpl; +import se.su.dsv.scipro.peer.PeerPortalImpl; +import se.su.dsv.scipro.peer.PeerRequestRepository; +import se.su.dsv.scipro.peer.PeerRequestService; +import se.su.dsv.scipro.peer.PeerRequestServiceImpl; +import se.su.dsv.scipro.peer.PeerReviewRepository; +import se.su.dsv.scipro.peer.PeerReviewService; +import se.su.dsv.scipro.peer.PeerReviewServiceImpl; +import se.su.dsv.scipro.plagiarism.PlagiarismControl; +import se.su.dsv.scipro.plagiarism.PlagiarismControlImpl; +import se.su.dsv.scipro.plagiarism.PlagiarismRequestRepository; +import se.su.dsv.scipro.plagiarism.urkund.UrkundApi; +import se.su.dsv.scipro.plagiarism.urkund.UrkundApiImpl; +import se.su.dsv.scipro.plagiarism.urkund.UrkundServiceImpl; +import se.su.dsv.scipro.plagiarism.urkund.UrkundSettingsRepository; +import se.su.dsv.scipro.plagiarism.urkund.UrkundSubmissionRepository; +import se.su.dsv.scipro.project.ProjectPeopleStatisticsServiceImpl; +import se.su.dsv.scipro.project.ProjectRepo; +import se.su.dsv.scipro.project.ProjectService; +import se.su.dsv.scipro.project.ProjectServiceImpl; +import se.su.dsv.scipro.projectpartner.ProjectPartnerServiceImpl; +import se.su.dsv.scipro.reflection.ReflectionService; +import se.su.dsv.scipro.reflection.ReflectionServiceImpl; +import se.su.dsv.scipro.report.GradeCalculatorServiceImpl; +import se.su.dsv.scipro.report.GradingReportService; +import se.su.dsv.scipro.report.GradingReportServiceImpl; +import se.su.dsv.scipro.report.GradingReportTemplateRepo; +import se.su.dsv.scipro.report.GradingReportTemplateRepoImpl; +import se.su.dsv.scipro.report.OppositionReportRepo; +import se.su.dsv.scipro.report.OppositionReportServiceImpl; +import se.su.dsv.scipro.report.ReportServiceImpl; +import se.su.dsv.scipro.report.SupervisorGradingReportRepository; +import se.su.dsv.scipro.reviewing.DecisionRepository; +import se.su.dsv.scipro.reviewing.FinalSeminarApprovalService; +import se.su.dsv.scipro.reviewing.FinalSeminarApprovalServiceImpl; +import se.su.dsv.scipro.reviewing.ProjectFinalSeminarStatisticsServiceImpl; +import se.su.dsv.scipro.reviewing.ReviewerAssignedDeadline; +import se.su.dsv.scipro.reviewing.ReviewerCapacityServiceImpl; +import se.su.dsv.scipro.reviewing.ReviewerDeadlineFollowupServiceImpl; +import se.su.dsv.scipro.reviewing.ReviewerDeadlineSettingsRepository; +import se.su.dsv.scipro.reviewing.ReviewerDeadlineSettingsService; +import se.su.dsv.scipro.reviewing.ReviewerDeadlineSettingsServiceImpl; +import se.su.dsv.scipro.reviewing.ReviewerInteractionService; +import se.su.dsv.scipro.reviewing.ReviewerInteractionServiceImpl; +import se.su.dsv.scipro.reviewing.ReviewerTargetRepository; +import se.su.dsv.scipro.reviewing.ReviewerThreadRepository; +import se.su.dsv.scipro.reviewing.ReviewingServiceImpl; +import se.su.dsv.scipro.reviewing.RoughDraftApprovalService; +import se.su.dsv.scipro.reviewing.RoughDraftApprovalServiceImpl; +import se.su.dsv.scipro.security.auth.AuthenticationProvider; +import se.su.dsv.scipro.security.auth.AuthenticationServiceImpl; +import se.su.dsv.scipro.security.auth.LocalAuthentication; +import se.su.dsv.scipro.springdata.serviceimpls.SupervisorServiceImpl; +import se.su.dsv.scipro.springdata.serviceimpls.UnitServiceImpl; +import se.su.dsv.scipro.springdata.serviceimpls.UserProfileServiceImpl; +import se.su.dsv.scipro.springdata.services.UserProfileService; +import se.su.dsv.scipro.sukat.LDAP; +import se.su.dsv.scipro.sukat.Sukat; +import se.su.dsv.scipro.survey.QuestionRepository; +import se.su.dsv.scipro.survey.SurveyRepository; +import se.su.dsv.scipro.survey.SurveyServiceImpl; +import se.su.dsv.scipro.system.CurrentUser; +import se.su.dsv.scipro.system.EventServiceImpl; +import se.su.dsv.scipro.system.ExternalResourceServiceImpl; +import se.su.dsv.scipro.system.FooterLinkRepo; +import se.su.dsv.scipro.system.FooterLinkServiceImpl; +import se.su.dsv.scipro.system.LocalUserSearch; +import se.su.dsv.scipro.system.PasswordRepo; +import se.su.dsv.scipro.system.PasswordService; +import se.su.dsv.scipro.system.PasswordServiceImpl; +import se.su.dsv.scipro.system.ProjectTypeService; +import se.su.dsv.scipro.system.ProjectTypeServiceImpl; +import se.su.dsv.scipro.system.ResearchAreaServiceImpl; +import se.su.dsv.scipro.system.UserNameServiceImpl; +import se.su.dsv.scipro.system.UserRepo; +import se.su.dsv.scipro.system.UserService; +import se.su.dsv.scipro.system.UserServiceImpl; +import se.su.dsv.scipro.thesislink.ExternalLinkServiceImpl; +import se.su.dsv.scipro.workerthreads.WorkerDataServiceImpl; + +import java.time.Clock; +import java.util.Set; + +@Configuration(proxyBeanMethods = false) +public class CoreConfig { + @Bean + public EventBus eventBus() { + return new EventBus(); + } + + @Bean + public GradingHistory gradingHistory(GradingHistoryEventRepository gradingHistoryEventRepository) { + return new GradingHistory(gradingHistoryEventRepository); + } + + @Bean + public OAuthSettings oAuthSettings( + @Value("${oauth.uri}") String uri, + @Value("${oauth.redirectUri}") String redirectUri, + @Value("${oauth.clientId}") String clientId, + @Value("${oauth.clientSecret}") String clientSecret) + { + return new OAuthSettings(uri, redirectUri, clientId, clientSecret); + } + + @Bean + public Sukat sukat() { + return new LDAP(); + } + + @Bean + public DaisyAPIImpl daisyAPI( + @Value("${daisy.api.url}") final String baseUrl, + @Value("${daisy.api.username}") final String user, + @Value("${daisy.api.password}") final String password) + { + return new DaisyAPIImpl(baseUrl, user, password); + } + + @Bean + public GradingServiceImpl gradingService(@Value("${service.grading.url}") final String url) { + return new GradingServiceImpl(url); + } + + @Bean + public OAuthServiceImpl oAuthService(OAuthSettings settings) { + return new OAuthServiceImpl(settings); + } + + @Bean + public FinalSeminarApprovalServiceImpl finalSeminarApprovalService( + Provider<EntityManager> em, + FileService fileDescriptionService, + EventBus eventBus, + DaysService daysService, + ReviewerDeadlineSettingsService reviewerDeadlineSettingsService) + { + return new FinalSeminarApprovalServiceImpl(em, fileDescriptionService, eventBus, daysService, reviewerDeadlineSettingsService); + } + + @Bean + public RoughDraftApprovalServiceImpl roughDraftApprovalService( + Provider<EntityManager> em, + FileService fileDescriptionService, + EventBus eventBus, + DaysService daysService, + ReviewerDeadlineSettingsService reviewerDeadlineSettingsService) + { + return new RoughDraftApprovalServiceImpl(em, eventBus, fileDescriptionService, daysService, reviewerDeadlineSettingsService); + } + + @Bean + public ActivityPlanServiceImpl activityPlanService(Provider<EntityManager> em) { + return new ActivityPlanServiceImpl(em); + } + + @Bean + public ActivityPlanTemplateServiceImpl activityPlanTemplateService(Provider<EntityManager> em) { + return new ActivityPlanTemplateServiceImpl(em); + } + + @Bean + public ActivityServiceImpl activityService(Provider<EntityManager> em) { + return new ActivityServiceImpl(em); + } + + @Bean + public ActivityPlanFacadeImpl activityPlanFacade( + EventBus eventBus, + ProjectFileService projectFileService, + ChecklistTemplateService checklistTemplateService, + DaysService daysService, + FileService fileService + ) + { + return new ActivityPlanFacadeImpl(eventBus, projectFileService, checklistTemplateService, daysService, + fileService); + } + + @Bean + public ApplicationPeriodFacadeImpl applicationPeriodFacade() { + return new ApplicationPeriodFacadeImpl(); + } + + @Bean + public ApplicationPeriodProjectTypeServiceImpl applicationPeriodProjectTypeService(Provider<EntityManager> em) { + return new ApplicationPeriodProjectTypeServiceImpl(em); + } + + @Bean + public ApplicationPeriodServiceImpl applicationPeriodService(Provider<EntityManager> em, Clock clock) { + return new ApplicationPeriodServiceImpl(em, clock); + } + + @Bean + public AuthenticationServiceImpl authenticationService(Set<AuthenticationProvider> authenticationProviders) { + return new AuthenticationServiceImpl(authenticationProviders); + } + + @Bean + public LocalAuthentication localAuthentication( + UserService userService, + PasswordService passwordService) + { + return new LocalAuthentication(userService, passwordService); + } + + @Bean + public BasicForumServiceImpl basicForumService( + ForumPostRepository forumPostRepository, + ForumPostReadStateRepository readStateRepository, + AbstractThreadRepository threadRepository, + FileService fileService, + EventBus eventBus) + { + return new BasicForumServiceImpl(forumPostRepository, readStateRepository, threadRepository, fileService, + eventBus); + } + + @Bean + public ChecklistAnswerServiceImpl checklistAnswerService(Provider<EntityManager> em) { + return new ChecklistAnswerServiceImpl(em); + } + + @Bean + public ChecklistServiceImpl checklistService(Provider<EntityManager> em) { + return new ChecklistServiceImpl(em); + } + + @Bean + public ChecklistTemplateServiceImpl checklistTemplateService(Provider<EntityManager> em) { + return new ChecklistTemplateServiceImpl(em); + } + + @Bean + public CommentServiceImpl commentService(Provider<EntityManager> em) { + return new CommentServiceImpl(em); + } + + @Bean + public DateServiceImpl dateService() { + return new DateServiceImpl(); + } + + @Bean + public DaysServiceImpl daysService(NonWorkDayPeriodService nonWorkDayPeriodService) { + return new DaysServiceImpl(nonWorkDayPeriodService); + } + + @Bean + public DeliveryConfigurationServiceImpl deliveryConfigurationService( + Provider<EntityManager> em, + UserProfileService userProfileService) + { + return new DeliveryConfigurationServiceImpl(em, userProfileService); + } + + @Bean + public EventServiceImpl eventService(Provider<EntityManager> em) { + return new EventServiceImpl(em); + } + + @Bean + public ExternalLinkServiceImpl externalLinkService(Provider<EntityManager> em) { + return new ExternalLinkServiceImpl(em); + } + + @Bean + public ExternalResourceServiceImpl externalResourceService(Provider<EntityManager> em) { + return new ExternalResourceServiceImpl(em); + } + + @Bean + public FileServiceImpl fileService( + Provider<EntityManager> em, + FileStore fileStore, + FileReferenceRepository fileReferenceRepository, + FileDescriptionRepo fileDescriptionRepository) + { + return new FileServiceImpl(em, fileReferenceRepository, fileDescriptionRepository, fileStore); + } + + @Bean + public FinalSeminarActiveParticipationServiceImpl finalSeminarActiveParticipationService(Provider<EntityManager> em) { + return new FinalSeminarActiveParticipationServiceImpl(em); + } + + @Bean + public FinalSeminarOppositionServiceImpl finalSeminarOppositionService(Provider<EntityManager> em) { + return new FinalSeminarOppositionServiceImpl(em); + } + + @Bean + public FinalSeminarRespondentServiceImpl finalSeminarRespondentService(Provider<EntityManager> em) { + return new FinalSeminarRespondentServiceImpl(em); + } + + @Bean + public FinalSeminarServiceImpl finalSeminarService( + Provider<EntityManager> em, + EventBus eventBus, + FileService fileService, + AuthorRepository authorRepository, + FinalSeminarOppositionRepo finalSeminarOppositionRepository, + FinalSeminarActiveParticipationRepository finalSeminarActiveParticipationRepository, + FinalSeminarRepository finalSeminarRepository, + Clock clock, + RoughDraftApprovalService roughDraftApprovalService) + { + return new FinalSeminarServiceImpl( + em, + eventBus, + authorRepository, + fileService, + finalSeminarOppositionRepository, + finalSeminarActiveParticipationRepository, + finalSeminarRepository, + clock, + roughDraftApprovalService); + } + + @Bean + public FinalSeminarSettingsServiceImpl finalSeminarSettingsService(Provider<EntityManager> em) { + return new FinalSeminarSettingsServiceImpl(em); + } + + @Bean + public FinalSeminarUploadControllerImpl finalSeminarUploadController( + EventBus eventBus, + FileService fileService, + FinalSeminarService finalSeminarService, + ProjectFileService projectFileService, + ProjectService projectService, + FinalSeminarSettingsService finalSeminarSettingsService, + PlagiarismControl plagiarismControl) + { + return new FinalSeminarUploadControllerImpl(projectService, fileService, finalSeminarSettingsService, + finalSeminarService, eventBus, projectFileService, plagiarismControl); + } + + @Bean + public FinalThesisServiceImpl finalThesisService( + Provider<EntityManager> em, + NotificationController notification, + ProjectFileService projectFile, + FileService fileService, + EventBus eventBus, + PlagiarismControl plagiarismControl, + GradingReportService gradingReportService) + { + return new FinalThesisServiceImpl(em, notification, projectFile, + fileService, eventBus, plagiarismControl, gradingReportService); + } + + @Bean + public FirstMeetingServiceImpl firstMeetingService( + Provider<EntityManager> em, + ActivityPlanFacade activityPlanFacade) + { + return new FirstMeetingServiceImpl(em, activityPlanFacade); + } + + @Bean + public FooterLinkServiceImpl footerLinkService(FooterLinkRepo footerLinkRepository) { + return new FooterLinkServiceImpl(footerLinkRepository); + } + + @Bean + public GeneralSystemSettingsServiceImpl generalSystemSettingsService(Provider<EntityManager> em) { + return new GeneralSystemSettingsServiceImpl(em); + } + + @Bean + public GradeCalculatorServiceImpl gradeCalculatorService(GradingReportService gradingReportService) { + return new GradeCalculatorServiceImpl(gradingReportService); + } + + @Bean + public GradingReportServiceImpl gradingReportService( + EventBus eventBus, + ThesisSubmissionHistoryService thesisSubmissionHistoryService, + Clock clock, + SupervisorGradingReportRepository supervisorGradingReportRepository, + GradingReportTemplateRepoImpl gradingReportTemplateRepo, + ProjectTypeService projectTypeService) + { + return new GradingReportServiceImpl( + eventBus, + thesisSubmissionHistoryService, + clock, + supervisorGradingReportRepository, + gradingReportTemplateRepo, + projectTypeService); + } + + @Bean + public GroupForumServiceImpl groupForumService( + EventBus eventBus, + GroupThreadRepository groupThreadRepository, + BasicForumService basicForumService) + { + return new GroupForumServiceImpl(groupThreadRepository, basicForumService, eventBus); + } + + @Bean + public GroupServiceImpl groupService(Provider<EntityManager> em) { + return new GroupServiceImpl(em); + } + + @Bean + public IdeaServiceImpl ideaService( + Provider<EntityManager> em, + ApplicationPeriodService applicationPeriodService, + FirstMeetingRepository firstMeetingRepository, + NotificationController notificationController, + ProjectService projectService, + GeneralSystemSettingsService generalSystemSettingsService, + TargetRepository targetRepository, + IdeaRepository ideaRepository, + Clock clock) + { + return new IdeaServiceImpl(em, applicationPeriodService, firstMeetingRepository, notificationController, + projectService, generalSystemSettingsService, targetRepository, ideaRepository, clock); + } + + @Bean + public KeywordServiceImpl keywordService(Provider<EntityManager> em) { + return new KeywordServiceImpl(em); + } + + @Bean + public LocalUserSearch localUserSearch(UserRepo userRepository) { + return new LocalUserSearch(userRepository); + } + + @Bean + public MailEventServiceImpl mailEventService(Provider<EntityManager> em) { + return new MailEventServiceImpl(em); + } + + @Bean + public MatchFollowUpServiceImpl matchFollowUpService(Provider<EntityManager> em) { + return new MatchFollowUpServiceImpl(em); + } + + @Bean + public MatchServiceImpl matchService(Provider<EntityManager> em) { + return new MatchServiceImpl(em); + } + + @Bean + public MilestoneActivityTemplateServiceImpl milestoneActivityTemplateService( + MilestoneActivityTemplateRepository milestoneActivityTemplateRepository) + { + return new MilestoneActivityTemplateServiceImpl(milestoneActivityTemplateRepository); + } + + @Bean + public MilestonePhaseTemplateServiceImpl milestonePhaseTemplateService(Provider<EntityManager> em) { + return new MilestonePhaseTemplateServiceImpl(em); + } + + @Bean + public MilestoneServiceImpl milestoneService( + Provider<EntityManager> em, + NotificationController notificationController) + { + return new MilestoneServiceImpl(notificationController, em); + } + + @Bean + public MilestoneStatisticsServiceImpl milestoneStatisticsService(Provider<EntityManager> em) { + return new MilestoneStatisticsServiceImpl(em); + } + + @Bean + public NationalSubjectCategoryServiceImpl nationalSubjectCategoryService( + NationalSubjectCategoryRepository nationalSubjectCategoryRepository) + { + return new NationalSubjectCategoryServiceImpl(nationalSubjectCategoryRepository); + } + + @Bean + public NonWorkDayPeriodServiceImpl nonWorkDayPeriodService(Provider<EntityManager> em) { + return new NonWorkDayPeriodServiceImpl(em); + } + + @Bean + public NoteServiceImpl noteService(Provider<EntityManager> em) { + return new NoteServiceImpl(em); + } + + @Bean + public NotificationServiceImpl notificationService(Provider<EntityManager> em) { + return new NotificationServiceImpl(em); + } + + @Bean + public OppositionReportServiceImpl oppositionReportService( + OppositionReportRepo oppositionReportRepository, + GradingReportTemplateRepo gradingReportTemplateRepository, + FileService fileService, + FinalSeminarOppositionRepo finalSeminarOppositionRepository) + { + return new OppositionReportServiceImpl(oppositionReportRepository, gradingReportTemplateRepository, + fileService, finalSeminarOppositionRepository); + } + + @Bean + public PasswordServiceImpl passwordService(PasswordRepo passwordRepo) { + return new PasswordServiceImpl(passwordRepo); + } + + @Bean + public PeerPortalImpl peerPortal( + FileService fileService, + PeerReviewRepository peerReviewRepository, + PeerRequestRepository peerRequestRepository, + EventBus eventBus, + ProjectFileService projectFileService, + DaysService daisyService, + Clock clock) + { + return new PeerPortalImpl(fileService, peerReviewRepository, peerRequestRepository, + eventBus, projectFileService, daisyService, clock); + } + + @Bean + public PeerRequestServiceImpl peerRequestService( + Provider<EntityManager> em, + EventBus eventBus, + FileService fileService) + { + return new PeerRequestServiceImpl(em, eventBus, fileService); + } + + @Bean + public PeerReviewServiceImpl peerReviewService( + Provider<EntityManager> em, + PeerReviewRepository peerReviewRepository) + { + return new PeerReviewServiceImpl(em, peerReviewRepository); + } + + @Bean + public PlagiarismControlImpl plagiarismControl( + FileService fileService, + PlagiarismRequestRepository plagiarismRequestRepository, + UrkundSubmissionRepository urkundSubmissionRepository) + { + return new PlagiarismControlImpl(plagiarismRequestRepository, urkundSubmissionRepository, fileService); + } + + @Bean + public PreliminaryMatchServiceImpl preliminaryMatchService(Provider<EntityManager> em, IdeaService ideaService) { + return new PreliminaryMatchServiceImpl(em, ideaService); + } + + @Bean + public ProgramServiceImpl programService(Provider<EntityManager> em) { + return new ProgramServiceImpl(em); + } + + @Bean + public ProjectFileServiceImpl projectFileService( + FileService fileService, + ProjectFileRepository projectFileRepository) + { + return new ProjectFileServiceImpl(fileService, projectFileRepository); + } + + @Bean + public ProjectFinalSeminarStatisticsServiceImpl projectFinalSeminarStatisticsService(Provider<EntityManager> em) { + return new ProjectFinalSeminarStatisticsServiceImpl(em); + } + + @Bean + public ProjectForumServiceImpl projectForumService( + EventBus eventBus, + BasicForumService basicForumService, + ProjectThreadRepository projectThreadRepository, + ForumPostRepository postRepository, + ProjectFileService projectFileService) + { + return new ProjectForumServiceImpl(projectThreadRepository, + postRepository, projectFileService, basicForumService, eventBus); + } + + @Bean + public ProjectPartnerServiceImpl projectPartnerService(Provider<EntityManager> em) { + return new ProjectPartnerServiceImpl(em); + } + + @Bean + public ProjectPeopleStatisticsServiceImpl projectPeopleStatisticsService(Provider<EntityManager> em) { + return new ProjectPeopleStatisticsServiceImpl(em); + } + + @Bean + public ProjectServiceImpl projectService( + Provider<EntityManager> em, + EventBus eventBus, + ProjectRepo projectRepo, + Clock clock) + { + return new ProjectServiceImpl(projectRepo, clock, eventBus, em); + } + + @Bean + public ProjectTypeServiceImpl projectTypeService(Provider<EntityManager> em) { + return new ProjectTypeServiceImpl(em); + } + + @Bean + public PublicationMetadataServiceImpl publicationMetadataService( + PublicationMetadataRepository publicationMetadataRepository) + { + return new PublicationMetadataServiceImpl(publicationMetadataRepository); + } + + @Bean + public ReflectionServiceImpl reflectionService( + AuthorRepository authorRepository, + FinalSeminarServiceImpl finalSeminarService) + { + return new ReflectionServiceImpl(authorRepository, finalSeminarService); + } + + @Bean + public ReceiverConfigurationServiceImpl receiverConfigurationService(Provider<EntityManager> em) { + return new ReceiverConfigurationServiceImpl(em); + } + + @Bean + public ReviewerDeadlineFollowupServiceImpl reviewerDeadlineFollowupService(Provider<EntityManager> em) { + return new ReviewerDeadlineFollowupServiceImpl(em); + } + + @Bean + public ZipReporter reporter( + FileService fileService, + ProjectService projectService, + FinalSeminarService finalSeminarService, + ProjectForumService projectForumService, + PeerReviewService peerReviewService, + PeerRequestService peerRequestService, + GroupService groupService, + GroupForumService groupForumService, + IdeaService ideaService, + GradingReportService gradingReportService, + ReviewerInteractionService reviewerInteractionService, + RoughDraftApprovalService roughDraftApprovalService, + FinalSeminarApprovalService finalSeminarApprovalService) + { + return new ZipReporter(fileService, projectService, finalSeminarService, projectForumService, peerReviewService, + peerRequestService, groupService, groupForumService, ideaService, gradingReportService, + reviewerInteractionService, roughDraftApprovalService, finalSeminarApprovalService); + } + + @Bean + public ReportServiceImpl reportService(Provider<EntityManager> em, FileService fileService) { + return new ReportServiceImpl(em, fileService); + } + + @Bean + public ResearchAreaServiceImpl researchAreaService(Provider<EntityManager> em) { + return new ResearchAreaServiceImpl(em); + } + + @Bean + public ReviewerInteractionServiceImpl reviewerInteractionService( + ReviewerThreadRepository reviewerThreadRepository, + BasicForumService forumService, + EventBus eventBus) + { + return new ReviewerInteractionServiceImpl(reviewerThreadRepository, forumService, eventBus); + } + + @Bean + public ReviewingServiceImpl reviewingService( + Provider<EntityManager> em, + EventBus eventBus, + FileService fileService) + { + return new ReviewingServiceImpl(em, fileService, eventBus); + } + + @Bean + public ReviewerCapacityServiceImpl reviewerCapacityService( + ReviewerTargetRepository reviewerTargetRepository, + DecisionRepository decisionRepository, + UserService userService, + ProjectService projectService, + EventBus eventBus) + { + return new ReviewerCapacityServiceImpl(reviewerTargetRepository, decisionRepository, userService, + projectService, eventBus); + } + + @Bean + public ReviewerDeadlineSettingsServiceImpl reviewerDeadlineSettingsService( + ReviewerDeadlineSettingsRepository reviewerDeadlineSettingsRepository) + { + return new ReviewerDeadlineSettingsServiceImpl(reviewerDeadlineSettingsRepository); + } + + @Bean + public SupervisorServiceImpl supervisorService(Provider<EntityManager> em) { + return new SupervisorServiceImpl(em); + } + + @Bean + public SurveyServiceImpl surveyService( + SurveyRepository surveyRepository, + QuestionRepository questionRepository, + FinalThesisService finalThesisService, + GeneralSystemSettingsService generalSystemSettingsService, + ReflectionService reflectionService) + { + return new SurveyServiceImpl(surveyRepository, questionRepository, finalThesisService, + generalSystemSettingsService, reflectionService); + } + + @Bean + public TargetServiceImpl targetService(Provider<EntityManager> em, IdeaService ideaService) { + return new TargetServiceImpl(em, ideaService); + } + + @Bean + public UnitServiceImpl unitService(Provider<EntityManager> em) { + return new UnitServiceImpl(em); + } + + @Bean + public UrkundApiImpl urkundApi( + UrkundSettingsRepository urkundSettingsRepository, + FileService fileService) + { + return new UrkundApiImpl(urkundSettingsRepository, fileService); + } + + @Bean + public UrkundServiceImpl urkundService( + UrkundApi urkundApi, + UrkundSubmissionRepository urkundSubmissionRepository, + Sukat sukat, + FileService fileService) + { + return new UrkundServiceImpl(urkundApi, urkundSubmissionRepository, sukat, fileService); + } + + @Bean + public UserNameServiceImpl userNameService(Provider<EntityManager> em) { + return new UserNameServiceImpl(em); + } + + @Bean + public UserProfileServiceImpl userProfileService(Provider<EntityManager> em) { + return new UserProfileServiceImpl(em); + } + + @Bean + public UserServiceImpl userService(Provider<EntityManager> em) { + return new UserServiceImpl(em); + } + + @Bean + public WorkerDataServiceImpl workerDataService(Provider<EntityManager> em) { + return new WorkerDataServiceImpl(em); + } + + @Bean + public NotificationControllerImpl notificationController( + NotificationServiceImpl notificationService, + NotificationMailFormatter notificationMailFormatter, + MailEventService mailEventService, + ReceiverConfigurationService receiverConfigurationService, + DeliveryConfigurationService deliveryConfigurationService, + Provider<CurrentUser> currentUserProvider) + { + return new NotificationControllerImpl(notificationService, + notificationMailFormatter, + mailEventService, receiverConfigurationService, deliveryConfigurationService, currentUserProvider); + } + + @Bean + public NotificationMailFormatterImpl notificationMailFormatter() { + return new NotificationMailFormatterImpl(); + } + + @Bean + public ReviewerAssignedDeadline reviewerAssignedDeadline( + EventBus eventBus, + ReviewerDeadlineSettingsService reviewerDeadlineSettingsService, + RoughDraftApprovalService roughDraftApprovalService, + FinalSeminarApprovalService finalSeminarApprovalService, + DaysService daysService, + Clock clock) + { + return new ReviewerAssignedDeadline(roughDraftApprovalService, finalSeminarApprovalService, + reviewerDeadlineSettingsService, daysService, eventBus, clock); + } + + @Bean + public DataInitializer dataInitializer() { + return new DataInitializer(); + } + + @Bean + public FinalSeminarActivityHandler finalSeminarActivityHandler( + ActivityPlanFacade activityPlanFacade, + ActivityFinalSeminarRepository activityFinalSeminarRepository, + EventBus eventBus) + { + return new FinalSeminarActivityHandler(activityPlanFacade, activityFinalSeminarRepository, eventBus); + } + + @Bean + public PostActivityUploadToForum postActivityUploadToForum( + EventBus eventBus, + ProjectForumService projectForumService, + ActivityThreadRepository activityThreadRepository) + { + return new PostActivityUploadToForum(projectForumService, activityThreadRepository, eventBus); + } + + @Bean + public ForumNotifications forumNotifications( + EventBus eventBus, + NotificationController notificationController, + ForumNotificationRepository forumNotificationRepository, + NotificationService notificationService) + { + return new ForumNotifications(eventBus, notificationController, forumNotificationRepository, + notificationService); + } + + @Bean + public ActivateCompletedMilestonesOnNewProjects activateCompletedMilestonesOnNewProjects( + EventBus eventBus, + MilestoneServiceImpl milestoneService, + PeerReviewService peerReviewService, + MilestoneActivityTemplateService milestoneActivityTemplateService, + FinalSeminarService finalSeminarService) + { + return new ActivateCompletedMilestonesOnNewProjects(peerReviewService, milestoneActivityTemplateService, + milestoneService, eventBus, finalSeminarService); + } + + @Bean + public FinalSeminarCreationSubscribers finalSeminarCreationSubscribers( + EventBus eventBus, + FinalSeminarServiceImpl finalSeminarService, + NotificationController notificationController, + AuthorRepository authorRepository) + { + return new FinalSeminarCreationSubscribers(authorRepository, finalSeminarService, notificationController, eventBus); + } + + @Bean + public ProjectStartNotifier projectStartNotifier(EventBus eventBus, NotificationController notificationController) { + return new ProjectStartNotifier(eventBus, notificationController); + } + + @Bean + public AddActivityPlanOnProjectStart addActivityPlanOnProjectStart( + ActivityPlanFacade activityPlanFacade, + EventBus eventBus) + { + return new AddActivityPlanOnProjectStart(activityPlanFacade, eventBus); + } + + @Bean + public Notifications notifications( + EventBus eventBus, + NotificationController notificationController, + NotificationService notificationService) + { + return new Notifications(notificationController, notificationService, eventBus); + } + + @Bean + public CommentThreadServiceImpl commentThreadService(CommentThreadRepo commentThreadRepository) { + return new CommentThreadServiceImpl(commentThreadRepository); + } + + @Bean + public NotificationEventServiceImpl notificationEventService(NotificationEventRepository notificationEventRepository) { + return new NotificationEventServiceImpl(notificationEventRepository); + } +} diff --git a/core/src/main/java/se/su/dsv/scipro/DataInitializer.java b/core/src/main/java/se/su/dsv/scipro/DataInitializer.java index 6720ffac7e..762ea0c32a 100644 --- a/core/src/main/java/se/su/dsv/scipro/DataInitializer.java +++ b/core/src/main/java/se/su/dsv/scipro/DataInitializer.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.checklist.ChecklistCategory; import se.su.dsv.scipro.match.ApplicationPeriod; import se.su.dsv.scipro.match.Keyword; diff --git a/core/src/main/java/se/su/dsv/scipro/RepositoryConfiguration.java b/core/src/main/java/se/su/dsv/scipro/RepositoryConfiguration.java new file mode 100644 index 0000000000..6a2167bc1f --- /dev/null +++ b/core/src/main/java/se/su/dsv/scipro/RepositoryConfiguration.java @@ -0,0 +1,285 @@ +package se.su.dsv.scipro; + +import jakarta.inject.Provider; +import jakarta.persistence.EntityManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import se.su.dsv.scipro.checklist.ChecklistCategoryRepoImpl; +import se.su.dsv.scipro.checklist.ChecklistQuestionRepoImpl; +import se.su.dsv.scipro.file.FileDescriptionRepoImpl; +import se.su.dsv.scipro.file.FileReferenceRepositoryImpl; +import se.su.dsv.scipro.file.ProjectFileRepositoryImpl; +import se.su.dsv.scipro.finalseminar.AuthorRepositoryImpl; +import se.su.dsv.scipro.finalseminar.FinalSeminarActiveParticipationRepositoryImpl; +import se.su.dsv.scipro.finalseminar.FinalSeminarOppositionRepoImpl; +import se.su.dsv.scipro.finalseminar.FinalSeminarRepositoryImpl; +import se.su.dsv.scipro.forum.AbstractThreadRepositoryImpl; +import se.su.dsv.scipro.forum.ForumPostReadStateRepositoryImpl; +import se.su.dsv.scipro.forum.ForumPostRepositoryImpl; +import se.su.dsv.scipro.forum.GroupThreadRepositoryImpl; +import se.su.dsv.scipro.forum.ProjectThreadRepositoryImpl; +import se.su.dsv.scipro.forum.notifications.ForumNotificationRepositoryImpl; +import se.su.dsv.scipro.grading.GradingHistoryEventRepositoryImpl; +import se.su.dsv.scipro.grading.NationalSubjectCategoryRepositoryImpl; +import se.su.dsv.scipro.grading.PublicationMetadataRepositoryImpl; +import se.su.dsv.scipro.integration.activityfinalseminar.ActivityFinalSeminarRepositoryImpl; +import se.su.dsv.scipro.integration.activityforum.ActivityThreadRepositoryImpl; +import se.su.dsv.scipro.match.FirstMeetingRepositoryImpl; +import se.su.dsv.scipro.match.IdeaRepositoryImpl; +import se.su.dsv.scipro.match.TargetRepositoryImpl; +import se.su.dsv.scipro.milestones.MilestoneActivityTemplateRepositoryImpl; +import se.su.dsv.scipro.notifications.NotificationEventRepositoryImpl; +import se.su.dsv.scipro.peer.CommentThreadRepoImpl; +import se.su.dsv.scipro.peer.PeerRequestRepositoryImpl; +import se.su.dsv.scipro.peer.PeerReviewRepositoryImpl; +import se.su.dsv.scipro.plagiarism.PlagiarismRequestRepositoryImpl; +import se.su.dsv.scipro.plagiarism.urkund.UrkundSettingsRepositoryImpl; +import se.su.dsv.scipro.plagiarism.urkund.UrkundSubmissionRepositoryImpl; +import se.su.dsv.scipro.project.ProjectRepoImpl; +import se.su.dsv.scipro.projectpartner.ProjectPartnerRepositoryImpl; +import se.su.dsv.scipro.report.GradingReportTemplateRepoImpl; +import se.su.dsv.scipro.report.OppositionReportRepoImpl; +import se.su.dsv.scipro.report.SupervisorGradingReportRepositoryImpl; +import se.su.dsv.scipro.reviewing.DecisionRepositoryImpl; +import se.su.dsv.scipro.reviewing.ReviewerDeadlineSettingsRepositoryImpl; +import se.su.dsv.scipro.reviewing.ReviewerTargetRepositoryImpl; +import se.su.dsv.scipro.reviewing.ReviewerThreadRepositoryImpl; +import se.su.dsv.scipro.survey.QuestionRepositoryImpl; +import se.su.dsv.scipro.survey.SurveyRepositoryImpl; +import se.su.dsv.scipro.system.FooterAddressRepoImpl; +import se.su.dsv.scipro.system.FooterLinkRepoImpl; +import se.su.dsv.scipro.system.PasswordRepoImpl; +import se.su.dsv.scipro.system.UserRepoImpl; + +@Configuration(proxyBeanMethods = false) +public class RepositoryConfiguration { + @Bean + public GradingHistoryEventRepositoryImpl gradingHistoryEventRepository(Provider<EntityManager> em) { + return new GradingHistoryEventRepositoryImpl(em); + } + + @Bean + public AbstractThreadRepositoryImpl abstractThreadRepository(Provider<EntityManager> em) { + return new AbstractThreadRepositoryImpl(em); + } + + @Bean + public ActivityFinalSeminarRepositoryImpl activityFinalSeminarRepository(Provider<EntityManager> em) { + return new ActivityFinalSeminarRepositoryImpl(em); + } + + @Bean + public ActivityThreadRepositoryImpl activityThreadRepository(Provider<EntityManager> em) { + return new ActivityThreadRepositoryImpl(em); + } + + @Bean + public AuthorRepositoryImpl authorRepository(Provider<EntityManager> em) { + return new AuthorRepositoryImpl(em); + } + + @Bean + public ChecklistCategoryRepoImpl checklistCategoryRepo(Provider<EntityManager> em) { + return new ChecklistCategoryRepoImpl(em); + } + + @Bean + public ChecklistQuestionRepoImpl checklistQuestionRepo(Provider<EntityManager> em) { + return new ChecklistQuestionRepoImpl(em); + } + + @Bean + public CommentThreadRepoImpl commentThreadRepo(Provider<EntityManager> em) { + return new CommentThreadRepoImpl(em); + } + + @Bean + public DecisionRepositoryImpl decisionRepository(Provider<EntityManager> em) { + return new DecisionRepositoryImpl(em); + } + + @Bean + public FileDescriptionRepoImpl fileDescriptionRepo(Provider<EntityManager> em) { + return new FileDescriptionRepoImpl(em); + } + + @Bean + public FinalSeminarActiveParticipationRepositoryImpl finalSeminarActiveParticipationRepository(Provider<EntityManager> em) { + return new FinalSeminarActiveParticipationRepositoryImpl(em); + } + + @Bean + public FinalSeminarRepositoryImpl finalSeminarRepository(Provider<EntityManager> em) { + return new FinalSeminarRepositoryImpl(em); + } + + @Bean + public FileReferenceRepositoryImpl fileReferenceRepository(Provider<EntityManager> em) { + return new FileReferenceRepositoryImpl(em); + } + + @Bean + public FinalSeminarOppositionRepoImpl finalSeminarOppositionRepo(Provider<EntityManager> em) { + return new FinalSeminarOppositionRepoImpl(em); + } + + @Bean + public FirstMeetingRepositoryImpl firstMeetingRepository(Provider<EntityManager> em) { + return new FirstMeetingRepositoryImpl(em); + } + + @Bean + public FooterAddressRepoImpl footerAddressRepo(Provider<EntityManager> em) { + return new FooterAddressRepoImpl(em); + } + + @Bean + public FooterLinkRepoImpl footerLinkRepo(Provider<EntityManager> em) { + return new FooterLinkRepoImpl(em); + } + + @Bean + public ForumNotificationRepositoryImpl forumNotificationRepository(Provider<EntityManager> em) { + return new ForumNotificationRepositoryImpl(em); + } + + @Bean + public ForumPostReadStateRepositoryImpl forumPostReadStateRepository(Provider<EntityManager> em) { + return new ForumPostReadStateRepositoryImpl(em); + } + + @Bean + public ForumPostRepositoryImpl forumPostRepository(Provider<EntityManager> em) { + return new ForumPostRepositoryImpl(em); + } + + @Bean + public GradingReportTemplateRepoImpl gradingReportTemplateRepo(Provider<EntityManager> em) { + return new GradingReportTemplateRepoImpl(em); + } + + @Bean + public GroupThreadRepositoryImpl groupThreadRepository(Provider<EntityManager> em) { + return new GroupThreadRepositoryImpl(em); + } + + @Bean + public IdeaRepositoryImpl ideaRepository(Provider<EntityManager> em) { + return new IdeaRepositoryImpl(em); + } + + @Bean + public MilestoneActivityTemplateRepositoryImpl milestoneActivityTemplateRepository(Provider<EntityManager> em) { + return new MilestoneActivityTemplateRepositoryImpl(em); + } + + @Bean + public NationalSubjectCategoryRepositoryImpl nationalSubjectCategoryRepository(Provider<EntityManager> em) { + return new NationalSubjectCategoryRepositoryImpl(em); + } + + @Bean + public OppositionReportRepoImpl oppositionReportRepo(Provider<EntityManager> em) { + return new OppositionReportRepoImpl(em); + } + + @Bean + public PasswordRepoImpl passwordRepo(Provider<EntityManager> em) { + return new PasswordRepoImpl(em); + } + + @Bean + public PeerRequestRepositoryImpl peerRequestRepository(Provider<EntityManager> em) { + return new PeerRequestRepositoryImpl(em); + } + + @Bean + public PeerReviewRepositoryImpl peerReviewRepository(Provider<EntityManager> em) { + return new PeerReviewRepositoryImpl(em); + } + + @Bean + public ProjectPartnerRepositoryImpl projectPartnerRepository(Provider<EntityManager> em) { + return new ProjectPartnerRepositoryImpl(em); + } + + @Bean + public ProjectRepoImpl projectRepo(Provider<EntityManager> em) { + return new ProjectRepoImpl(em); + } + + @Bean + public ProjectThreadRepositoryImpl projectThreadRepository(Provider<EntityManager> em) { + return new ProjectThreadRepositoryImpl(em); + } + + @Bean + public PublicationMetadataRepositoryImpl publicationMetadataRepository(Provider<EntityManager> em) { + return new PublicationMetadataRepositoryImpl(em); + } + + @Bean + public QuestionRepositoryImpl questionRepository(Provider<EntityManager> em) { + return new QuestionRepositoryImpl(em); + } + + @Bean + public ReviewerDeadlineSettingsRepositoryImpl reviewerDeadlineSettingsRepository(Provider<EntityManager> em) { + return new ReviewerDeadlineSettingsRepositoryImpl(em); + } + + @Bean + public ReviewerTargetRepositoryImpl reviewerTargetRepository(Provider<EntityManager> em) { + return new ReviewerTargetRepositoryImpl(em); + } + + @Bean + public ReviewerThreadRepositoryImpl reviewerThreadRepository(Provider<EntityManager> em) { + return new ReviewerThreadRepositoryImpl(em); + } + + @Bean + public SurveyRepositoryImpl surveyRepository(Provider<EntityManager> em) { + return new SurveyRepositoryImpl(em); + } + + @Bean + public TargetRepositoryImpl targetRepository(Provider<EntityManager> em) { + return new TargetRepositoryImpl(em); + } + + @Bean + public UrkundSettingsRepositoryImpl urkundSettingsRepository(Provider<EntityManager> em) { + return new UrkundSettingsRepositoryImpl(em); + } + + @Bean + public UrkundSubmissionRepositoryImpl urkundSubmissionRepository(Provider<EntityManager> em) { + return new UrkundSubmissionRepositoryImpl(em); + } + + @Bean + public UserRepoImpl userRepo(Provider<EntityManager> em) { + return new UserRepoImpl(em); + } + + @Bean + public PlagiarismRequestRepositoryImpl plagiarismRequestRepository(Provider<EntityManager> em) { + return new PlagiarismRequestRepositoryImpl(em); + } + + @Bean + public ProjectFileRepositoryImpl projectFileRepository(Provider<EntityManager> em) { + return new ProjectFileRepositoryImpl(em); + } + + @Bean + public NotificationEventRepositoryImpl notificationEventRepository(Provider<EntityManager> em) { + return new NotificationEventRepositoryImpl(em); + } + + @Bean + public SupervisorGradingReportRepositoryImpl supervisorGradingReportRepository(Provider<EntityManager> em) { + return new SupervisorGradingReportRepositoryImpl(em); + } +} diff --git a/core/src/main/java/se/su/dsv/scipro/activityplan/ActivityPlanFacadeImpl.java b/core/src/main/java/se/su/dsv/scipro/activityplan/ActivityPlanFacadeImpl.java index d211c1cbac..4f7955f835 100755 --- a/core/src/main/java/se/su/dsv/scipro/activityplan/ActivityPlanFacadeImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/activityplan/ActivityPlanFacadeImpl.java @@ -1,7 +1,7 @@ package se.su.dsv.scipro.activityplan; import com.google.common.eventbus.EventBus; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import se.su.dsv.scipro.system.Pageable; diff --git a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistAnswerServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistAnswerServiceImpl.java index 1e1893ccda..20a612c25f 100644 --- a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistAnswerServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistAnswerServiceImpl.java @@ -9,7 +9,7 @@ import jakarta.persistence.EntityManager; public class ChecklistAnswerServiceImpl extends AbstractServiceImpl<ChecklistAnswer, Long> implements ChecklistAnswerService { @Inject - protected ChecklistAnswerServiceImpl(Provider<EntityManager> em) { + public ChecklistAnswerServiceImpl(Provider<EntityManager> em) { super(em, ChecklistAnswer.class, QChecklistAnswer.checklistAnswer); } } diff --git a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistCategoryRepo.java b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistCategoryRepo.java index 9b5883089e..64b595d29e 100755 --- a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistCategoryRepo.java +++ b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistCategoryRepo.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.checklist; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.JpaRepository; import se.su.dsv.scipro.system.QueryDslPredicateExecutor; diff --git a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistQuestionRepo.java b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistQuestionRepo.java index 410c90439a..3fb6407ebc 100755 --- a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistQuestionRepo.java +++ b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistQuestionRepo.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.checklist; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.JpaRepository; import se.su.dsv.scipro.system.QueryDslPredicateExecutor; diff --git a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistServiceImpl.java index cba683c25a..9a9a9c234e 100755 --- a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.checklist; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.activityplan.QActivity; import se.su.dsv.scipro.activityplan.QActivityPlan; import se.su.dsv.scipro.project.Project; diff --git a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistTemplateServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistTemplateServiceImpl.java index 0e43b8c13d..336d0e8b58 100755 --- a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistTemplateServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistTemplateServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.checklist; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import com.querydsl.core.types.dsl.BooleanExpression; import se.su.dsv.scipro.system.Pageable; import se.su.dsv.scipro.project.Project; diff --git a/core/src/main/java/se/su/dsv/scipro/daisyExternal/DaisyExternalModule.java b/core/src/main/java/se/su/dsv/scipro/daisyExternal/DaisyExternalModule.java deleted file mode 100644 index 63de05fdfb..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/daisyExternal/DaisyExternalModule.java +++ /dev/null @@ -1,20 +0,0 @@ -package se.su.dsv.scipro.daisyExternal; - -import com.google.inject.Key; -import com.google.inject.PrivateModule; -import com.google.inject.Scopes; -import com.google.inject.name.Names; -import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; -import se.su.dsv.scipro.daisyExternal.http.DaisyAPIImpl; - -public class DaisyExternalModule extends PrivateModule { - @Override - protected void configure() { - requireBinding(Key.get(String.class, Names.named("daisy.api.url"))); - requireBinding(Key.get(String.class, Names.named("daisy.api.username"))); - requireBinding(Key.get(String.class, Names.named("daisy.api.password"))); - - bind(DaisyAPI.class).to(DaisyAPIImpl.class).in(Scopes.SINGLETON); - expose(DaisyAPI.class); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/events/EventModule.java b/core/src/main/java/se/su/dsv/scipro/events/EventModule.java deleted file mode 100644 index 61fb042f87..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/events/EventModule.java +++ /dev/null @@ -1,15 +0,0 @@ -package se.su.dsv.scipro.events; - -import com.google.common.eventbus.EventBus; -import com.google.inject.AbstractModule; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class EventModule extends AbstractModule { - private static final Logger LOGGER = LoggerFactory.getLogger(EventModule.class); - - @Override - protected void configure() { - bind(EventBus.class).toInstance(new EventBus((throwable, context) -> LOGGER.error("Could not dispatch event: " + context.getSubscriber() + " to " + context.getSubscriberMethod(), throwable))); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/file/FileDescriptionRepo.java b/core/src/main/java/se/su/dsv/scipro/file/FileDescriptionRepo.java index eccb9da1eb..c649d10bfe 100755 --- a/core/src/main/java/se/su/dsv/scipro/file/FileDescriptionRepo.java +++ b/core/src/main/java/se/su/dsv/scipro/file/FileDescriptionRepo.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.file; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.JpaRepository; import se.su.dsv.scipro.system.QueryDslPredicateExecutor; diff --git a/core/src/main/java/se/su/dsv/scipro/file/FileModule.java b/core/src/main/java/se/su/dsv/scipro/file/FileModule.java deleted file mode 100644 index 82cc9172ea..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/file/FileModule.java +++ /dev/null @@ -1,16 +0,0 @@ -package se.su.dsv.scipro.file; - -import com.google.inject.AbstractModule; - -public class FileModule extends AbstractModule { - @Override - protected void configure() { - bind(FileService.class).to(FileServiceImpl.class); - bind(ProjectFileService.class).to(ProjectFileServiceImpl.class); - bind(ProjectFileRepository.class).to(ProjectFileRepositoryImpl.class); - bind(FileReferenceRepository.class).to(FileReferenceRepositoryImpl.class); - bind(FileDescriptionRepo.class).to(FileDescriptionRepoImpl.class); - - requireBinding(FileStore.class); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/file/FileReferenceRepository.java b/core/src/main/java/se/su/dsv/scipro/file/FileReferenceRepository.java index a942b50e60..3264448133 100644 --- a/core/src/main/java/se/su/dsv/scipro/file/FileReferenceRepository.java +++ b/core/src/main/java/se/su/dsv/scipro/file/FileReferenceRepository.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.file; -interface FileReferenceRepository { +public interface FileReferenceRepository { FileReference create(FileReference fileReference); void delete(FileReference fileReference); diff --git a/core/src/main/java/se/su/dsv/scipro/file/FileReferenceRepositoryImpl.java b/core/src/main/java/se/su/dsv/scipro/file/FileReferenceRepositoryImpl.java index cacc3f7a16..25e00cf450 100644 --- a/core/src/main/java/se/su/dsv/scipro/file/FileReferenceRepositoryImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/file/FileReferenceRepositoryImpl.java @@ -1,16 +1,16 @@ package se.su.dsv.scipro.file; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.AbstractRepository; import jakarta.inject.Inject; import jakarta.inject.Provider; import jakarta.persistence.EntityManager; -class FileReferenceRepositoryImpl extends AbstractRepository implements FileReferenceRepository { +public class FileReferenceRepositoryImpl extends AbstractRepository implements FileReferenceRepository { @Inject - FileReferenceRepositoryImpl(final Provider<EntityManager> em) { + public FileReferenceRepositoryImpl(final Provider<EntityManager> em) { super(em); } diff --git a/core/src/main/java/se/su/dsv/scipro/file/FileServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/file/FileServiceImpl.java index 2fe1f634d6..c6643f50ad 100755 --- a/core/src/main/java/se/su/dsv/scipro/file/FileServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/file/FileServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.file; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.AbstractServiceImpl; import jakarta.inject.Inject; diff --git a/core/src/main/java/se/su/dsv/scipro/file/ProjectFileServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/file/ProjectFileServiceImpl.java index e995fd1831..db099d6323 100644 --- a/core/src/main/java/se/su/dsv/scipro/file/ProjectFileServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/file/ProjectFileServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.file; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.Pageable; import se.su.dsv.scipro.project.Project; diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionRepo.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionRepo.java index 7def75b680..46957a9678 100755 --- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionRepo.java +++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionRepo.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.finalseminar; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.JpaRepository; import se.su.dsv.scipro.system.QueryDslPredicateExecutor; import se.su.dsv.scipro.system.ProjectType; diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarRepositoryImpl.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarRepositoryImpl.java index f17e41be75..40e72964a7 100644 --- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarRepositoryImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarRepositoryImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.finalseminar; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import jakarta.persistence.EntityManager; import se.su.dsv.scipro.system.AbstractRepository; @@ -9,7 +9,7 @@ import jakarta.inject.Provider; public class FinalSeminarRepositoryImpl extends AbstractRepository implements FinalSeminarRepository { @Inject - protected FinalSeminarRepositoryImpl(Provider<EntityManager> em) { + public FinalSeminarRepositoryImpl(Provider<EntityManager> em) { super(em); } diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarServiceImpl.java index e3510ddfae..b5514bcd3e 100755 --- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarServiceImpl.java @@ -1,7 +1,7 @@ package se.su.dsv.scipro.finalseminar; import com.google.common.eventbus.EventBus; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.dsl.BooleanExpression; import jakarta.persistence.EntityManager; diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarSettingsServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarSettingsServiceImpl.java index 24aa74c59e..c912f35abb 100755 --- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarSettingsServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarSettingsServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.finalseminar; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.AbstractServiceImpl; import jakarta.inject.Inject; diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarUploadControllerImpl.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarUploadControllerImpl.java index 5feff42af2..2613d77c32 100755 --- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarUploadControllerImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarUploadControllerImpl.java @@ -1,7 +1,7 @@ package se.su.dsv.scipro.finalseminar; import com.google.common.eventbus.EventBus; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import se.su.dsv.scipro.file.*; diff --git a/core/src/main/java/se/su/dsv/scipro/finalthesis/FinalThesisServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/finalthesis/FinalThesisServiceImpl.java index 98b775c07b..41251d1700 100644 --- a/core/src/main/java/se/su/dsv/scipro/finalthesis/FinalThesisServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/finalthesis/FinalThesisServiceImpl.java @@ -1,7 +1,7 @@ package se.su.dsv.scipro.finalthesis; import com.google.common.eventbus.EventBus; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Predicate; import jakarta.persistence.EntityManager; diff --git a/core/src/main/java/se/su/dsv/scipro/firstmeeting/FirstMeetingModule.java b/core/src/main/java/se/su/dsv/scipro/firstmeeting/FirstMeetingModule.java deleted file mode 100644 index e567605a8d..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/firstmeeting/FirstMeetingModule.java +++ /dev/null @@ -1,11 +0,0 @@ -package se.su.dsv.scipro.firstmeeting; - -import com.google.inject.AbstractModule; -import se.su.dsv.scipro.firstmeeting.FirstMeetingReminderWorker.FirstMeetingReminderWorkerSchedule; - -public class FirstMeetingModule extends AbstractModule { - @Override - public void configure() { - bind(FirstMeetingReminderWorkerSchedule.class).asEagerSingleton(); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/forum/BasicForumServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/forum/BasicForumServiceImpl.java index 05642970d2..0dae3383bb 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/BasicForumServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/BasicForumServiceImpl.java @@ -1,7 +1,7 @@ package se.su.dsv.scipro.forum; import com.google.common.eventbus.EventBus; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.file.FileReference; import se.su.dsv.scipro.file.FileService; import se.su.dsv.scipro.forum.dataobjects.ForumPost; diff --git a/core/src/main/java/se/su/dsv/scipro/forum/ForumModule.java b/core/src/main/java/se/su/dsv/scipro/forum/ForumModule.java deleted file mode 100644 index 7346fd1166..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/forum/ForumModule.java +++ /dev/null @@ -1,26 +0,0 @@ -package se.su.dsv.scipro.forum; - -import com.google.inject.PrivateModule; - -public class ForumModule extends PrivateModule { - @Override - protected void configure() { - bind(AbstractThreadRepository.class).to(AbstractThreadRepositoryImpl.class); - bind(ForumPostReadStateRepository.class).to(ForumPostReadStateRepositoryImpl.class); - bind(ForumPostRepository.class).to(ForumPostRepositoryImpl.class); - bind(ProjectThreadRepository.class).to(ProjectThreadRepositoryImpl.class); - bind(GroupThreadRepository.class).to(GroupThreadRepositoryImpl.class); - - expose(ProjectThreadRepository.class); - expose(GroupThreadRepository.class); - - bind(ProjectForumService.class).to(ProjectForumServiceImpl.class); - bind(GroupForumService.class).to(GroupForumServiceImpl.class); - - expose(ProjectForumService.class); - expose(GroupForumService.class); - - bind(BasicForumService.class).to(BasicForumServiceImpl.class); - expose(BasicForumService.class); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/forum/ForumPostReadStateRepository.java b/core/src/main/java/se/su/dsv/scipro/forum/ForumPostReadStateRepository.java index 4d385c0255..00dd52bb7c 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/ForumPostReadStateRepository.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/ForumPostReadStateRepository.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.forum; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.JpaRepository; import se.su.dsv.scipro.system.QueryDslPredicateExecutor; import se.su.dsv.scipro.forum.dataobjects.ForumPost; diff --git a/core/src/main/java/se/su/dsv/scipro/forum/ForumPostReadStateRepositoryImpl.java b/core/src/main/java/se/su/dsv/scipro/forum/ForumPostReadStateRepositoryImpl.java index 909c57693f..862884445c 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/ForumPostReadStateRepositoryImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/ForumPostReadStateRepositoryImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.forum; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import jakarta.persistence.LockModeType; import se.su.dsv.scipro.forum.dataobjects.ForumPost; import se.su.dsv.scipro.forum.dataobjects.ForumPostReadState; diff --git a/core/src/main/java/se/su/dsv/scipro/forum/ForumPostRepository.java b/core/src/main/java/se/su/dsv/scipro/forum/ForumPostRepository.java index 0b39495268..92e3afb1c8 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/ForumPostRepository.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/ForumPostRepository.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.forum; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.JpaRepository; import se.su.dsv.scipro.system.QueryDslPredicateExecutor; import se.su.dsv.scipro.forum.dataobjects.ForumPost; diff --git a/core/src/main/java/se/su/dsv/scipro/forum/GroupForumServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/forum/GroupForumServiceImpl.java index bed0169c09..0ba81e0b92 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/GroupForumServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/GroupForumServiceImpl.java @@ -1,7 +1,7 @@ package se.su.dsv.scipro.forum; import com.google.common.eventbus.EventBus; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.forum.dataobjects.ForumPost; import se.su.dsv.scipro.forum.dataobjects.ForumThread; import se.su.dsv.scipro.forum.dataobjects.GroupThread; diff --git a/core/src/main/java/se/su/dsv/scipro/forum/GroupThreadRepository.java b/core/src/main/java/se/su/dsv/scipro/forum/GroupThreadRepository.java index 37e0a30d31..2c254d5bd2 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/GroupThreadRepository.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/GroupThreadRepository.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.forum; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.JpaRepository; import se.su.dsv.scipro.system.QueryDslPredicateExecutor; import se.su.dsv.scipro.forum.dataobjects.GroupThread; diff --git a/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumServiceImpl.java index 7ed3e1715c..1825a16197 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumServiceImpl.java @@ -1,7 +1,7 @@ package se.su.dsv.scipro.forum; import com.google.common.eventbus.EventBus; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.file.FileSource; import se.su.dsv.scipro.file.ProjectFileService; import se.su.dsv.scipro.forum.dataobjects.ForumPost; diff --git a/core/src/main/java/se/su/dsv/scipro/forum/ProjectThreadRepository.java b/core/src/main/java/se/su/dsv/scipro/forum/ProjectThreadRepository.java index b50913b764..cbe28506a1 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/ProjectThreadRepository.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/ProjectThreadRepository.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.forum; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.JpaRepository; import se.su.dsv.scipro.system.QueryDslPredicateExecutor; import se.su.dsv.scipro.forum.dataobjects.ProjectThread; diff --git a/core/src/main/java/se/su/dsv/scipro/forum/notifications/ForumNotifications.java b/core/src/main/java/se/su/dsv/scipro/forum/notifications/ForumNotifications.java index b294608351..5b1ff17920 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/notifications/ForumNotifications.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/notifications/ForumNotifications.java @@ -2,7 +2,7 @@ package se.su.dsv.scipro.forum.notifications; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.forum.dataobjects.ForumPost; import se.su.dsv.scipro.forum.ForumPostReadEvent; import se.su.dsv.scipro.forum.NewGroupForumReplyEvent; diff --git a/core/src/main/java/se/su/dsv/scipro/forum/notifications/ForumNotificationsModule.java b/core/src/main/java/se/su/dsv/scipro/forum/notifications/ForumNotificationsModule.java deleted file mode 100644 index 2a77013615..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/forum/notifications/ForumNotificationsModule.java +++ /dev/null @@ -1,11 +0,0 @@ -package se.su.dsv.scipro.forum.notifications; - -import com.google.inject.AbstractModule; - -public class ForumNotificationsModule extends AbstractModule { - @Override - public void configure() { - bind(ForumNotificationRepository.class).to(ForumNotificationRepositoryImpl.class); - bind(ForumNotifications.class).asEagerSingleton(); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/gdpr/GDPRModule.java b/core/src/main/java/se/su/dsv/scipro/gdpr/GDPRModule.java deleted file mode 100644 index 65a3f3ae8f..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/gdpr/GDPRModule.java +++ /dev/null @@ -1,12 +0,0 @@ -package se.su.dsv.scipro.gdpr; - -import com.google.inject.PrivateModule; - -public class GDPRModule extends PrivateModule { - @Override - protected void configure() { - bind(Reporter.class).to(ZipReporter.class); - - expose(Reporter.class); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/generalsystemsettings/GeneralSystemSettingsServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/generalsystemsettings/GeneralSystemSettingsServiceImpl.java index 1550844b4e..5450f5b837 100755 --- a/core/src/main/java/se/su/dsv/scipro/generalsystemsettings/GeneralSystemSettingsServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/generalsystemsettings/GeneralSystemSettingsServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.generalsystemsettings; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.AbstractServiceImpl; import jakarta.inject.Inject; diff --git a/core/src/main/java/se/su/dsv/scipro/grading/GradingHistoryEventRepositoryImpl.java b/core/src/main/java/se/su/dsv/scipro/grading/GradingHistoryEventRepositoryImpl.java index 68b25d1cd0..de3f36ac13 100644 --- a/core/src/main/java/se/su/dsv/scipro/grading/GradingHistoryEventRepositoryImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/grading/GradingHistoryEventRepositoryImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.grading; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import jakarta.persistence.EntityManager; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.AbstractRepository; diff --git a/core/src/main/java/se/su/dsv/scipro/grading/GradingModule.java b/core/src/main/java/se/su/dsv/scipro/grading/GradingModule.java deleted file mode 100644 index e67d559b77..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/grading/GradingModule.java +++ /dev/null @@ -1,37 +0,0 @@ -package se.su.dsv.scipro.grading; - -import com.google.inject.Key; -import com.google.inject.PrivateModule; -import com.google.inject.name.Names; -import se.su.dsv.scipro.report.GradingReportServiceImpl; - -public class GradingModule extends PrivateModule { - @Override - protected void configure() { - requireBinding(Key.get(String.class, Names.named("service.grading.url"))); - bind(GradingService.class).to(GradingServiceImpl.class); - - expose(GradingService.class); - - bind(PublicationMetadataRepository.class).to(PublicationMetadataRepositoryImpl.class); - bind(PublicationMetadataService.class).to(PublicationMetadataServiceImpl.class); - expose(PublicationMetadataService.class); - - bind(ExaminerTimelineService.class).to(GradingHistory.class); - expose(ExaminerTimelineService.class); - bind(GradingHistoryEventRepository.class).to(GradingHistoryEventRepositoryImpl.class); - bind(ThesisRejectionHistoryService.class).to(GradingHistory.class); - expose(ThesisRejectionHistoryService.class); - bind(ThesisApprovedHistoryService.class).to(GradingHistory.class); - expose(ThesisApprovedHistoryService.class); - bind(ThesisSubmissionHistoryService.class).to(GradingHistory.class); - expose(ThesisSubmissionHistoryService.class); - - bind(NationalSubjectCategoryRepository.class).to(NationalSubjectCategoryRepositoryImpl.class); - bind(NationalSubjectCategoryService.class).to(NationalSubjectCategoryServiceImpl.class); - expose(NationalSubjectCategoryService.class); - - bind(GradingReportTemplateService.class).to(GradingReportServiceImpl.class); - expose(GradingReportTemplateService.class); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/grading/NationalSubjectCategoryRepositoryImpl.java b/core/src/main/java/se/su/dsv/scipro/grading/NationalSubjectCategoryRepositoryImpl.java index 2a6d009a47..90c2723739 100644 --- a/core/src/main/java/se/su/dsv/scipro/grading/NationalSubjectCategoryRepositoryImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/grading/NationalSubjectCategoryRepositoryImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.grading; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import jakarta.persistence.EntityManager; import se.su.dsv.scipro.system.AbstractRepository; diff --git a/core/src/main/java/se/su/dsv/scipro/grading/PublicationMetadataRepository.java b/core/src/main/java/se/su/dsv/scipro/grading/PublicationMetadataRepository.java index 05702c1d93..10c37dab9e 100644 --- a/core/src/main/java/se/su/dsv/scipro/grading/PublicationMetadataRepository.java +++ b/core/src/main/java/se/su/dsv/scipro/grading/PublicationMetadataRepository.java @@ -2,7 +2,7 @@ package se.su.dsv.scipro.grading; import se.su.dsv.scipro.project.Project; -interface PublicationMetadataRepository { +public interface PublicationMetadataRepository { void save(PublicationMetadata publicationMetadata); PublicationMetadata findByProject(Project project); diff --git a/core/src/main/java/se/su/dsv/scipro/grading/PublicationMetadataRepositoryImpl.java b/core/src/main/java/se/su/dsv/scipro/grading/PublicationMetadataRepositoryImpl.java index f1b2ac5a38..503b62f6ec 100644 --- a/core/src/main/java/se/su/dsv/scipro/grading/PublicationMetadataRepositoryImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/grading/PublicationMetadataRepositoryImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.grading; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import jakarta.persistence.EntityManager; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.AbstractRepository; @@ -8,9 +8,9 @@ import se.su.dsv.scipro.system.AbstractRepository; import jakarta.inject.Inject; import jakarta.inject.Provider; -class PublicationMetadataRepositoryImpl extends AbstractRepository implements PublicationMetadataRepository { +public class PublicationMetadataRepositoryImpl extends AbstractRepository implements PublicationMetadataRepository { @Inject - PublicationMetadataRepositoryImpl(Provider<EntityManager> em) { + public PublicationMetadataRepositoryImpl(Provider<EntityManager> em) { super(em); } diff --git a/core/src/main/java/se/su/dsv/scipro/grading/PublicationMetadataServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/grading/PublicationMetadataServiceImpl.java index 26f0e1801b..684e24ae7b 100644 --- a/core/src/main/java/se/su/dsv/scipro/grading/PublicationMetadataServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/grading/PublicationMetadataServiceImpl.java @@ -6,11 +6,11 @@ import se.su.dsv.scipro.system.Language; import jakarta.inject.Inject; import java.util.Objects; -class PublicationMetadataServiceImpl implements PublicationMetadataService { +public class PublicationMetadataServiceImpl implements PublicationMetadataService { private final PublicationMetadataRepository publicationMetadataRepository; @Inject - PublicationMetadataServiceImpl(PublicationMetadataRepository publicationMetadataRepository) { + public PublicationMetadataServiceImpl(PublicationMetadataRepository publicationMetadataRepository) { this.publicationMetadataRepository = publicationMetadataRepository; } diff --git a/core/src/main/java/se/su/dsv/scipro/integration/activityfinalseminar/ActivityFinalSeminarModule.java b/core/src/main/java/se/su/dsv/scipro/integration/activityfinalseminar/ActivityFinalSeminarModule.java deleted file mode 100644 index 0d5d8bf9a4..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/integration/activityfinalseminar/ActivityFinalSeminarModule.java +++ /dev/null @@ -1,11 +0,0 @@ -package se.su.dsv.scipro.integration.activityfinalseminar; - -import com.google.inject.AbstractModule; - -public class ActivityFinalSeminarModule extends AbstractModule { - @Override - protected void configure() { - bind(FinalSeminarActivityHandler.class).asEagerSingleton(); - bind(ActivityFinalSeminarRepository.class).to(ActivityFinalSeminarRepositoryImpl.class); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/integration/activityfinalseminar/ActivityFinalSeminarRepository.java b/core/src/main/java/se/su/dsv/scipro/integration/activityfinalseminar/ActivityFinalSeminarRepository.java index 87191121e6..6f1af4098c 100644 --- a/core/src/main/java/se/su/dsv/scipro/integration/activityfinalseminar/ActivityFinalSeminarRepository.java +++ b/core/src/main/java/se/su/dsv/scipro/integration/activityfinalseminar/ActivityFinalSeminarRepository.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.integration.activityfinalseminar; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.JpaRepository; import se.su.dsv.scipro.system.QueryDslPredicateExecutor; import se.su.dsv.scipro.finalseminar.FinalSeminar; diff --git a/core/src/main/java/se/su/dsv/scipro/integration/activityforum/ActivityForumModule.java b/core/src/main/java/se/su/dsv/scipro/integration/activityforum/ActivityForumModule.java deleted file mode 100644 index c14a655f13..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/integration/activityforum/ActivityForumModule.java +++ /dev/null @@ -1,11 +0,0 @@ -package se.su.dsv.scipro.integration.activityforum; - -import com.google.inject.AbstractModule; - -public class ActivityForumModule extends AbstractModule { - @Override - protected void configure() { - bind(PostActivityUploadToForum.class).asEagerSingleton(); - bind(ActivityThreadRepository.class).to(ActivityThreadRepositoryImpl.class); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/mail/PrintingMailer.java b/core/src/main/java/se/su/dsv/scipro/mail/PrintingMailer.java index a5c7f597be..179bffc02c 100644 --- a/core/src/main/java/se/su/dsv/scipro/mail/PrintingMailer.java +++ b/core/src/main/java/se/su/dsv/scipro/mail/PrintingMailer.java @@ -6,7 +6,7 @@ import se.su.dsv.scipro.file.FileDescription; import java.util.Arrays; import java.util.UUID; -class PrintingMailer implements Mailer { +public class PrintingMailer implements Mailer { @Override public MailResult mail(final String fromName, final String fromEmail, final String[] recipients, final String subject, final String message, final FileDescription attachment) { return new MailResult() { diff --git a/core/src/main/java/se/su/dsv/scipro/match/AllowAllIdeaCreationJudge.java b/core/src/main/java/se/su/dsv/scipro/match/AllowAllIdeaCreationJudge.java index f5e0035fa5..6a91588ff1 100644 --- a/core/src/main/java/se/su/dsv/scipro/match/AllowAllIdeaCreationJudge.java +++ b/core/src/main/java/se/su/dsv/scipro/match/AllowAllIdeaCreationJudge.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.match; -class AllowAllIdeaCreationJudge implements IdeaCreationJudge { +public class AllowAllIdeaCreationJudge implements IdeaCreationJudge { @Override public Decision ruling(Idea idea) { return Decision.allowed(); diff --git a/core/src/main/java/se/su/dsv/scipro/match/ApplicationPeriodServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/match/ApplicationPeriodServiceImpl.java index 0156c88bd8..29499c6f0c 100755 --- a/core/src/main/java/se/su/dsv/scipro/match/ApplicationPeriodServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/match/ApplicationPeriodServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.match; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.Expressions; import se.su.dsv.scipro.system.PageRequest; diff --git a/core/src/main/java/se/su/dsv/scipro/match/FirstMeetingRepository.java b/core/src/main/java/se/su/dsv/scipro/match/FirstMeetingRepository.java index 7714a267a9..caa4bab050 100755 --- a/core/src/main/java/se/su/dsv/scipro/match/FirstMeetingRepository.java +++ b/core/src/main/java/se/su/dsv/scipro/match/FirstMeetingRepository.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.match; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.JpaRepository; import se.su.dsv.scipro.system.QueryDslPredicateExecutor; diff --git a/core/src/main/java/se/su/dsv/scipro/match/IdeaServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/match/IdeaServiceImpl.java index 07a468f894..d3c410eb05 100755 --- a/core/src/main/java/se/su/dsv/scipro/match/IdeaServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/match/IdeaServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.match; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Predicate; import com.querydsl.core.types.dsl.BooleanExpression; diff --git a/core/src/main/java/se/su/dsv/scipro/match/KeywordServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/match/KeywordServiceImpl.java index 44c702b1aa..9eb0a58232 100755 --- a/core/src/main/java/se/su/dsv/scipro/match/KeywordServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/match/KeywordServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.match; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import com.querydsl.core.types.dsl.BooleanExpression; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/core/src/main/java/se/su/dsv/scipro/match/MatchModule.java b/core/src/main/java/se/su/dsv/scipro/match/MatchModule.java deleted file mode 100644 index 28e19d2295..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/match/MatchModule.java +++ /dev/null @@ -1,26 +0,0 @@ -package se.su.dsv.scipro.match; - -import com.google.inject.AbstractModule; -import com.google.inject.multibindings.OptionalBinder; - -public class MatchModule extends AbstractModule { - @Override - protected void configure() { - OptionalBinder.newOptionalBinder(binder(), IdeaCreationJudge.class) - .setDefault().to(AllowAllIdeaCreationJudge.class); - bind(ProjectStartNotifier.class).asEagerSingleton(); - bind(AddActivityPlanOnProjectStart.class).asEagerSingleton(); - bind(ApplicationPeriodService.class).to(ApplicationPeriodServiceImpl.class); - bind(IdeaService.class).to(IdeaServiceImpl.class); - bind(FirstMeetingRepository.class).to(FirstMeetingRepositoryImpl.class); - bind(KeywordService.class).to(KeywordServiceImpl.class); - bind(MatchService.class).to(MatchServiceImpl.class); - bind(ProgramService.class).to(ProgramServiceImpl.class); - bind(MatchFollowUpService.class).to(MatchFollowUpServiceImpl.class); - bind(TargetService.class).to(TargetServiceImpl.class); - bind(ApplicationPeriodProjectTypeService.class).to(ApplicationPeriodProjectTypeServiceImpl.class); - bind(PreliminaryMatchService.class).to(PreliminaryMatchServiceImpl.class); - bind(IdeaRepository.class).to(IdeaRepositoryImpl.class); - bind(TargetRepository.class).to(TargetRepositoryImpl.class); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/match/ProgramServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/match/ProgramServiceImpl.java index e759f53f93..925831af46 100644 --- a/core/src/main/java/se/su/dsv/scipro/match/ProgramServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/match/ProgramServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.match; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import com.querydsl.core.types.dsl.BooleanExpression; import se.su.dsv.scipro.system.PageRequest; import se.su.dsv.scipro.system.Sort; diff --git a/core/src/main/java/se/su/dsv/scipro/milestones/MilestoneActivityTemplateRepository.java b/core/src/main/java/se/su/dsv/scipro/milestones/MilestoneActivityTemplateRepository.java index e43bb892e8..8d8aaaeb33 100644 --- a/core/src/main/java/se/su/dsv/scipro/milestones/MilestoneActivityTemplateRepository.java +++ b/core/src/main/java/se/su/dsv/scipro/milestones/MilestoneActivityTemplateRepository.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.milestones; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.JpaRepository; import se.su.dsv.scipro.system.QueryDslPredicateExecutor; import se.su.dsv.scipro.milestones.dataobjects.MilestoneActivityTemplate; diff --git a/core/src/main/java/se/su/dsv/scipro/milestones/service/impl/MilestonePhaseTemplateServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/milestones/service/impl/MilestonePhaseTemplateServiceImpl.java index f5bd91a316..197e947bda 100644 --- a/core/src/main/java/se/su/dsv/scipro/milestones/service/impl/MilestonePhaseTemplateServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/milestones/service/impl/MilestonePhaseTemplateServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.milestones.service.impl; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.Sort; import se.su.dsv.scipro.milestones.dataobjects.MilestonePhaseTemplate; import se.su.dsv.scipro.milestones.dataobjects.QMilestonePhaseTemplate; diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/NotificationControllerImpl.java b/core/src/main/java/se/su/dsv/scipro/notifications/NotificationControllerImpl.java index 8bd1a88a13..0a4a6e08f4 100755 --- a/core/src/main/java/se/su/dsv/scipro/notifications/NotificationControllerImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/NotificationControllerImpl.java @@ -1,6 +1,5 @@ package se.su.dsv.scipro.notifications; -import com.google.inject.ProvisionException; import se.su.dsv.scipro.data.dataobjects.Member; import se.su.dsv.scipro.finalseminar.FinalSeminar; import se.su.dsv.scipro.group.Group; @@ -94,7 +93,7 @@ public class NotificationControllerImpl implements NotificationController { try { return currentUserProvider.get().get(); } - catch (ProvisionException ignored) { + catch (RuntimeException ignored) { return null; } } diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/NotificationModule.java b/core/src/main/java/se/su/dsv/scipro/notifications/NotificationModule.java deleted file mode 100644 index 507ca4bcab..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/notifications/NotificationModule.java +++ /dev/null @@ -1,28 +0,0 @@ -package se.su.dsv.scipro.notifications; - -import com.google.inject.PrivateModule; -import se.su.dsv.scipro.notifications.interfaces.NotificationMailFormatter; -import se.su.dsv.scipro.notifications.interfaces.impl.NotificationMailFormatterImpl; - -public class NotificationModule extends PrivateModule { - - public static final String NOTIFICATION_RELATIVE_PAGE_URL = "notification"; - - @Override - protected void configure() { - bind(Notifications.class).asEagerSingleton(); - - bind(NotificationService.class).to(NotificationServiceImpl.class); - expose(NotificationService.class); - - bind(NotificationEventRepository.class).to(NotificationEventRepositoryImpl.class); - bind(NotificationEventService.class).to(NotificationEventServiceImpl.class); - expose(NotificationEventService.class); - - bind(NotificationMailFormatter.class).to(NotificationMailFormatterImpl.class); - expose(NotificationMailFormatter.class); - bind(NotificationController.class).to(NotificationControllerImpl.class); - expose(NotificationController.class); - } - -} diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/NotificationServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/notifications/NotificationServiceImpl.java index 826991801f..6c460a0741 100755 --- a/core/src/main/java/se/su/dsv/scipro/notifications/NotificationServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/NotificationServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.notifications; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Predicate; import se.su.dsv.scipro.system.Pageable; diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/interfaces/impl/NotificationMailFormatterImpl.java b/core/src/main/java/se/su/dsv/scipro/notifications/interfaces/impl/NotificationMailFormatterImpl.java index cdf67a52d4..b8aeadcb99 100755 --- a/core/src/main/java/se/su/dsv/scipro/notifications/interfaces/impl/NotificationMailFormatterImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/interfaces/impl/NotificationMailFormatterImpl.java @@ -8,7 +8,6 @@ import se.su.dsv.scipro.finalseminar.FinalSeminar; import se.su.dsv.scipro.finalseminar.FinalSeminarService; import se.su.dsv.scipro.generalsystemsettings.GeneralSystemSettings; import se.su.dsv.scipro.generalsystemsettings.GeneralSystemSettingsService; -import se.su.dsv.scipro.notifications.NotificationModule; import se.su.dsv.scipro.notifications.dataobject.*; import se.su.dsv.scipro.notifications.interfaces.NotificationMailFormatter; import se.su.dsv.scipro.project.Project; @@ -158,7 +157,7 @@ public class NotificationMailFormatterImpl implements NotificationMailFormatter private String getAbsoluteURL(final Notification notification) { final String baseUrl = systemSettingsService.getGeneralSystemSettingsInstance().getSciproURL(); long id = notification.getNotificationEvent().getId(); - return baseUrl + "/" + NotificationModule.NOTIFICATION_RELATIVE_PAGE_URL + "?id=" + id; + return baseUrl + "/" + "notification" + "?id=" + id; } String makeProperty(Object... parts) { diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/settings/service/DeliveryConfigurationServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/notifications/settings/service/DeliveryConfigurationServiceImpl.java index 285b9f6c0a..75f7624ac6 100644 --- a/core/src/main/java/se/su/dsv/scipro/notifications/settings/service/DeliveryConfigurationServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/settings/service/DeliveryConfigurationServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.notifications.settings.service; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.notifications.dataobject.Notification; import se.su.dsv.scipro.notifications.dataobject.Notification.Type; import se.su.dsv.scipro.notifications.settings.entities.DeliveryConfiguration; diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/settings/service/ReceiverConfigurationServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/notifications/settings/service/ReceiverConfigurationServiceImpl.java index 37befe6c34..596c2e3821 100644 --- a/core/src/main/java/se/su/dsv/scipro/notifications/settings/service/ReceiverConfigurationServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/settings/service/ReceiverConfigurationServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.notifications.settings.service; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.data.dataobjects.Member; import se.su.dsv.scipro.notifications.dataobject.Notification; import se.su.dsv.scipro.notifications.settings.entities.QReceiverConfiguration; diff --git a/core/src/main/java/se/su/dsv/scipro/oauth/OAuthModule.java b/core/src/main/java/se/su/dsv/scipro/oauth/OAuthModule.java deleted file mode 100644 index bce825afe1..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/oauth/OAuthModule.java +++ /dev/null @@ -1,25 +0,0 @@ -package se.su.dsv.scipro.oauth; - -import com.google.inject.PrivateModule; -import com.google.inject.Provides; - -import jakarta.inject.Named; - -public class OAuthModule extends PrivateModule { - @Override - protected void configure() { - bind(OAuthService.class).to(OAuthServiceImpl.class); - - expose(OAuthService.class); - } - - @Provides - OAuthSettings settings( - @Named("oauth.uri") String uri, - @Named("oauth.redirectUri") String redirectUri, - @Named("oauth.clientId") String clientId, - @Named("oauth.clientSecret") String clientSecret) - { - return new OAuthSettings(uri, redirectUri, clientId, clientSecret); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/oauth/OAuthSettings.java b/core/src/main/java/se/su/dsv/scipro/oauth/OAuthSettings.java index a8b41b8648..2a20bcf204 100644 --- a/core/src/main/java/se/su/dsv/scipro/oauth/OAuthSettings.java +++ b/core/src/main/java/se/su/dsv/scipro/oauth/OAuthSettings.java @@ -1,4 +1,4 @@ package se.su.dsv.scipro.oauth; -record OAuthSettings(String uri, String redirectUri, String clientId, String clientSecret) { +public record OAuthSettings(String uri, String redirectUri, String clientId, String clientSecret) { } diff --git a/core/src/main/java/se/su/dsv/scipro/peer/CommentServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/peer/CommentServiceImpl.java index db26096621..63723ecf16 100644 --- a/core/src/main/java/se/su/dsv/scipro/peer/CommentServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/peer/CommentServiceImpl.java @@ -10,7 +10,7 @@ import java.util.List; public class CommentServiceImpl extends AbstractServiceImpl<Comment, Long> implements CommentService { @Inject - protected CommentServiceImpl(Provider<EntityManager> em) { + public CommentServiceImpl(Provider<EntityManager> em) { super(em, Comment.class, QComment.comment1); } diff --git a/core/src/main/java/se/su/dsv/scipro/peer/CommentThreadRepo.java b/core/src/main/java/se/su/dsv/scipro/peer/CommentThreadRepo.java index 025bb02da1..8210abd3c5 100644 --- a/core/src/main/java/se/su/dsv/scipro/peer/CommentThreadRepo.java +++ b/core/src/main/java/se/su/dsv/scipro/peer/CommentThreadRepo.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.peer; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.JpaRepository; import se.su.dsv.scipro.system.QueryDslPredicateExecutor; diff --git a/core/src/main/java/se/su/dsv/scipro/peer/CommentThreadServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/peer/CommentThreadServiceImpl.java index 82d1e68e53..604e36b9a5 100644 --- a/core/src/main/java/se/su/dsv/scipro/peer/CommentThreadServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/peer/CommentThreadServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.peer; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import jakarta.inject.Inject; diff --git a/core/src/main/java/se/su/dsv/scipro/peer/PeerModule.java b/core/src/main/java/se/su/dsv/scipro/peer/PeerModule.java deleted file mode 100644 index 0fdd05980c..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/peer/PeerModule.java +++ /dev/null @@ -1,13 +0,0 @@ -package se.su.dsv.scipro.peer; - -import com.google.inject.AbstractModule; -import com.google.inject.multibindings.Multibinder; -import se.su.dsv.scipro.system.Lifecycle; - -public class PeerModule extends AbstractModule { - @Override - protected void configure() { - Multibinder.newSetBinder(binder(), Lifecycle.class) - .addBinding().to(PeerWorkerSchedules.class); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/peer/PeerPortalImpl.java b/core/src/main/java/se/su/dsv/scipro/peer/PeerPortalImpl.java index 5582001f6a..aa6b178072 100755 --- a/core/src/main/java/se/su/dsv/scipro/peer/PeerPortalImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/peer/PeerPortalImpl.java @@ -1,7 +1,7 @@ package se.su.dsv.scipro.peer; import com.google.common.eventbus.EventBus; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import se.su.dsv.scipro.file.FileReference; @@ -152,7 +152,7 @@ public class PeerPortalImpl implements PeerPortal, PerformReviewService { } @Override - @Transactional(ignore = {TooShortCommentException.class, MissingAnswerException.class}) + @Transactional(dontRollbackOn = {TooShortCommentException.class, MissingAnswerException.class}) public void submit(PeerReview review, Optional<FileUpload> upload) { review.submit(); final Optional<FileReference> fileDescription = storePeerReviewFileUpload(upload); diff --git a/core/src/main/java/se/su/dsv/scipro/peer/PeerRequestRepository.java b/core/src/main/java/se/su/dsv/scipro/peer/PeerRequestRepository.java index d6ca147c68..1a5c7439ff 100755 --- a/core/src/main/java/se/su/dsv/scipro/peer/PeerRequestRepository.java +++ b/core/src/main/java/se/su/dsv/scipro/peer/PeerRequestRepository.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.peer; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.JpaRepository; import se.su.dsv.scipro.system.QueryDslPredicateExecutor; diff --git a/core/src/main/java/se/su/dsv/scipro/peer/PeerRequestServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/peer/PeerRequestServiceImpl.java index b79394efd6..ad77dcfe22 100755 --- a/core/src/main/java/se/su/dsv/scipro/peer/PeerRequestServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/peer/PeerRequestServiceImpl.java @@ -1,7 +1,7 @@ package se.su.dsv.scipro.peer; import com.google.common.eventbus.EventBus; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.dsl.BooleanExpression; import se.su.dsv.scipro.system.Pageable; diff --git a/core/src/main/java/se/su/dsv/scipro/plagiarism/PlagiarismControlImpl.java b/core/src/main/java/se/su/dsv/scipro/plagiarism/PlagiarismControlImpl.java index b21bd32fe9..d72913163d 100755 --- a/core/src/main/java/se/su/dsv/scipro/plagiarism/PlagiarismControlImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/plagiarism/PlagiarismControlImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.plagiarism; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.file.FileDescription; import se.su.dsv.scipro.file.FileReference; import se.su.dsv.scipro.file.FileService; diff --git a/core/src/main/java/se/su/dsv/scipro/plagiarism/PlagiarismModule.java b/core/src/main/java/se/su/dsv/scipro/plagiarism/PlagiarismModule.java deleted file mode 100644 index 3f862ea21c..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/plagiarism/PlagiarismModule.java +++ /dev/null @@ -1,11 +0,0 @@ -package se.su.dsv.scipro.plagiarism; - -import com.google.inject.AbstractModule; - -public class PlagiarismModule extends AbstractModule { - @Override - protected void configure() { - bind(PlagiarismControl.class).to(PlagiarismControlImpl.class); - bind(PlagiarismRequestRepository.class).to(PlagiarismRequestRepositoryImpl.class); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundApiImpl.java b/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundApiImpl.java index 774dfdda3a..5a5f58f929 100644 --- a/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundApiImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundApiImpl.java @@ -36,7 +36,7 @@ public class UrkundApiImpl implements UrkundApi { private final FileService fileService; @Inject - UrkundApiImpl(final UrkundSettingsRepository urkundSettingsRepository, FileService fileService) { + public UrkundApiImpl(final UrkundSettingsRepository urkundSettingsRepository, FileService fileService) { this.urkundSettingsRepository = urkundSettingsRepository; this.fileService = fileService; objectMapper = new ObjectMapper(); diff --git a/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundModule.java b/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundModule.java deleted file mode 100644 index 573a3a5559..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundModule.java +++ /dev/null @@ -1,26 +0,0 @@ -package se.su.dsv.scipro.plagiarism.urkund; - -import com.google.inject.AbstractModule; -import com.google.inject.Provides; -import com.google.inject.Scopes; -import se.su.dsv.scipro.sukat.Sukat; - -import jakarta.persistence.EntityManager; - -public class UrkundModule extends AbstractModule { - @Override - protected void configure() { - bind(UrkundService.class).to(UrkundServiceImpl.class); - bind(UrkundSubmissionRepository.class).to(UrkundSubmissionRepositoryImpl.class); - bind(UrkundApi.class).to(UrkundApiImpl.class).in(Scopes.SINGLETON); - bind(UrkundSettingsRepository.class).to(UrkundSettingsRepositoryImpl.class); - - requireBinding(EntityManager.class); - requireBinding(Sukat.class); - } - - @Provides - public UrkundSettings urkundSettings(UrkundSettingsRepository urkundSettingsRepository) { - return urkundSettingsRepository.getSettings(); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundServiceImpl.java index 8eac423c9b..e83125690b 100644 --- a/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.plagiarism.urkund; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.file.FileDescription; import se.su.dsv.scipro.file.FileReference; import se.su.dsv.scipro.file.FileService; diff --git a/core/src/main/java/se/su/dsv/scipro/profiles/CurrentProfile.java b/core/src/main/java/se/su/dsv/scipro/profiles/CurrentProfile.java index 679ba53157..6bf6f2bd19 100755 --- a/core/src/main/java/se/su/dsv/scipro/profiles/CurrentProfile.java +++ b/core/src/main/java/se/su/dsv/scipro/profiles/CurrentProfile.java @@ -1,14 +1,10 @@ package se.su.dsv.scipro.profiles; -import jakarta.inject.Inject; -import jakarta.inject.Named; - public class CurrentProfile { private String currentProfileString; - @Inject - public void setCurrentProfileString(@Named("profile") String currentProfileString) { + public void setCurrentProfileString(String currentProfileString) { this.currentProfileString = currentProfileString; } diff --git a/core/src/main/java/se/su/dsv/scipro/project/ProjectPeopleStatisticsServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/project/ProjectPeopleStatisticsServiceImpl.java index 9a2862ae63..ada1db066b 100644 --- a/core/src/main/java/se/su/dsv/scipro/project/ProjectPeopleStatisticsServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/project/ProjectPeopleStatisticsServiceImpl.java @@ -10,7 +10,7 @@ import jakarta.persistence.EntityManager; public class ProjectPeopleStatisticsServiceImpl extends AbstractServiceImpl<Project, Long> implements ProjectPeopleStatisticsService { @Inject - protected ProjectPeopleStatisticsServiceImpl(Provider<EntityManager> em) { + public ProjectPeopleStatisticsServiceImpl(Provider<EntityManager> em) { super(em, Project.class, QProject.project); } diff --git a/core/src/main/java/se/su/dsv/scipro/project/ProjectRepo.java b/core/src/main/java/se/su/dsv/scipro/project/ProjectRepo.java index 43892156ca..a1c985044f 100755 --- a/core/src/main/java/se/su/dsv/scipro/project/ProjectRepo.java +++ b/core/src/main/java/se/su/dsv/scipro/project/ProjectRepo.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.project; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.JpaRepository; import se.su.dsv.scipro.system.QueryDslPredicateExecutor; import se.su.dsv.scipro.system.User; diff --git a/core/src/main/java/se/su/dsv/scipro/project/ProjectRepoImpl.java b/core/src/main/java/se/su/dsv/scipro/project/ProjectRepoImpl.java index f8dfb462bd..8211412568 100644 --- a/core/src/main/java/se/su/dsv/scipro/project/ProjectRepoImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/project/ProjectRepoImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.project; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.GenericRepo; import se.su.dsv.scipro.system.User; diff --git a/core/src/main/java/se/su/dsv/scipro/project/ProjectServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/project/ProjectServiceImpl.java index 617f39e795..e52cae2397 100755 --- a/core/src/main/java/se/su/dsv/scipro/project/ProjectServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/project/ProjectServiceImpl.java @@ -1,7 +1,7 @@ package se.su.dsv.scipro.project; import com.google.common.eventbus.EventBus; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Predicate; import com.querydsl.core.types.dsl.BooleanExpression; diff --git a/core/src/main/java/se/su/dsv/scipro/projectpartner/ProjectPartnerRepositoryImpl.java b/core/src/main/java/se/su/dsv/scipro/projectpartner/ProjectPartnerRepositoryImpl.java index 63dada7bf6..a437f162d5 100644 --- a/core/src/main/java/se/su/dsv/scipro/projectpartner/ProjectPartnerRepositoryImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/projectpartner/ProjectPartnerRepositoryImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.projectpartner; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.AbstractRepository; import jakarta.inject.Inject; diff --git a/core/src/main/java/se/su/dsv/scipro/projectpartner/ProjectPartnerServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/projectpartner/ProjectPartnerServiceImpl.java index 3b39364a33..5af5e3a0a7 100644 --- a/core/src/main/java/se/su/dsv/scipro/projectpartner/ProjectPartnerServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/projectpartner/ProjectPartnerServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.projectpartner; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.JPAExpressions; import se.su.dsv.scipro.system.Pageable; diff --git a/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionModule.java b/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionModule.java deleted file mode 100644 index 872fd7d8dd..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionModule.java +++ /dev/null @@ -1,13 +0,0 @@ -package se.su.dsv.scipro.reflection; - -import com.google.inject.AbstractModule; -import se.su.dsv.scipro.finalseminar.AuthorRepository; - -public class ReflectionModule extends AbstractModule { - @Override - protected void configure() { - requireBinding(AuthorRepository.class); - - bind(ReflectionService.class).to(ReflectionServiceImpl.class); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionServiceImpl.java index ccd23a6244..bdc36bc904 100644 --- a/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.reflection; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.finalseminar.AuthorRepository; import se.su.dsv.scipro.finalseminar.FinalSeminarService; import se.su.dsv.scipro.project.Author; @@ -9,12 +9,12 @@ import se.su.dsv.scipro.system.User; import jakarta.inject.Inject; -class ReflectionServiceImpl implements ReflectionService { +public class ReflectionServiceImpl implements ReflectionService { private final AuthorRepository authorRepository; private final FinalSeminarService finalSeminarService; @Inject - ReflectionServiceImpl(AuthorRepository authorRepository, FinalSeminarService finalSeminarService) { + public ReflectionServiceImpl(AuthorRepository authorRepository, FinalSeminarService finalSeminarService) { this.authorRepository = authorRepository; this.finalSeminarService = finalSeminarService; } diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradingReportServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/report/GradingReportServiceImpl.java index 6f9b1a9824..1dd53e1665 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/GradingReportServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/report/GradingReportServiceImpl.java @@ -1,7 +1,7 @@ package se.su.dsv.scipro.report; import com.google.common.eventbus.EventBus; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.finalseminar.FinalSeminarOpposition; import se.su.dsv.scipro.grading.GradingBasis; import se.su.dsv.scipro.grading.GradingReportTemplateService; @@ -133,6 +133,7 @@ public class GradingReportServiceImpl implements GradingReportTemplateService, G } @Override + @Transactional public List<SupervisorGradingReport> getSupervisorGradingReports(Project project) { List<SupervisorGradingReport> gradingReports = new ArrayList<>(); for (User user : project.getProjectParticipants()) { diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplateRepoImpl.java b/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplateRepoImpl.java index 8cf96941a1..7eec180ce5 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplateRepoImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplateRepoImpl.java @@ -1,8 +1,8 @@ package se.su.dsv.scipro.report; -import com.google.inject.persist.Transactional; import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.JPQLQuery; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.grading.GradingReportTemplateUpdate; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.GenericRepo; diff --git a/core/src/main/java/se/su/dsv/scipro/report/OppositionReportServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/report/OppositionReportServiceImpl.java index 417e7a15bf..231fe6f692 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/OppositionReportServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/report/OppositionReportServiceImpl.java @@ -1,7 +1,7 @@ package se.su.dsv.scipro.report; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.file.FileReference; import se.su.dsv.scipro.file.FileService; import se.su.dsv.scipro.finalseminar.FinalSeminarOpposition; diff --git a/core/src/main/java/se/su/dsv/scipro/report/ReportServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/report/ReportServiceImpl.java index f8ba6bd969..44d938d819 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/ReportServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/report/ReportServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.report; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.file.FileReference; import se.su.dsv.scipro.file.FileService; import se.su.dsv.scipro.file.FileUpload; diff --git a/core/src/main/java/se/su/dsv/scipro/reviewing/FinalSeminarApprovalServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/reviewing/FinalSeminarApprovalServiceImpl.java index 5d8e123342..fec755260c 100644 --- a/core/src/main/java/se/su/dsv/scipro/reviewing/FinalSeminarApprovalServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/reviewing/FinalSeminarApprovalServiceImpl.java @@ -1,7 +1,7 @@ package se.su.dsv.scipro.reviewing; import com.google.common.eventbus.EventBus; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.file.FileReference; import se.su.dsv.scipro.file.FileService; import se.su.dsv.scipro.file.FileUpload; diff --git a/core/src/main/java/se/su/dsv/scipro/reviewing/ProjectFinalSeminarStatisticsServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/reviewing/ProjectFinalSeminarStatisticsServiceImpl.java index 736c9d4120..9a5239e570 100644 --- a/core/src/main/java/se/su/dsv/scipro/reviewing/ProjectFinalSeminarStatisticsServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/reviewing/ProjectFinalSeminarStatisticsServiceImpl.java @@ -27,7 +27,7 @@ import static com.querydsl.core.types.dsl.Expressions.anyOf; public class ProjectFinalSeminarStatisticsServiceImpl extends AbstractServiceImpl<Project, Long> implements ProjectFinalSeminarStatisticsService { @Inject - protected ProjectFinalSeminarStatisticsServiceImpl(Provider<EntityManager> em) { + public ProjectFinalSeminarStatisticsServiceImpl(Provider<EntityManager> em) { super(em, Project.class, QProject.project); } diff --git a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerCapacityServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerCapacityServiceImpl.java index c758523db5..08e67aa38b 100644 --- a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerCapacityServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerCapacityServiceImpl.java @@ -1,7 +1,7 @@ package se.su.dsv.scipro.reviewing; import com.google.common.eventbus.EventBus; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.project.ProjectService; import se.su.dsv.scipro.project.ReviewerAssignedEvent; @@ -25,7 +25,7 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Stream; -class ReviewerCapacityServiceImpl implements ReviewerCapacityService, ReviewerAssignmentService { +public class ReviewerCapacityServiceImpl implements ReviewerCapacityService, ReviewerAssignmentService { private final ReviewerTargetRepository reviewerTargetRepository; private final DecisionRepository decisionRepository; private final UserService userService; @@ -33,7 +33,7 @@ class ReviewerCapacityServiceImpl implements ReviewerCapacityService, ReviewerAs private final EventBus eventBus; @Inject - ReviewerCapacityServiceImpl( + public ReviewerCapacityServiceImpl( ReviewerTargetRepository reviewerTargetRepository, DecisionRepository decisionRepository, UserService userService, diff --git a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerDeadlineSettingsRepository.java b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerDeadlineSettingsRepository.java index 0094b9e7dc..e95b191bb8 100644 --- a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerDeadlineSettingsRepository.java +++ b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerDeadlineSettingsRepository.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.reviewing; -interface ReviewerDeadlineSettingsRepository { +public interface ReviewerDeadlineSettingsRepository { ReviewerDeadlineSettings findOne(long instanceId); ReviewerDeadlineSettings save(ReviewerDeadlineSettings entity); diff --git a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerDeadlineSettingsRepositoryImpl.java b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerDeadlineSettingsRepositoryImpl.java index bcaf1e434e..6839c0cac5 100644 --- a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerDeadlineSettingsRepositoryImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerDeadlineSettingsRepositoryImpl.java @@ -6,12 +6,12 @@ import se.su.dsv.scipro.system.AbstractRepository; import jakarta.inject.Inject; import jakarta.inject.Provider; -class ReviewerDeadlineSettingsRepositoryImpl +public class ReviewerDeadlineSettingsRepositoryImpl extends AbstractRepository implements ReviewerDeadlineSettingsRepository { @Inject - ReviewerDeadlineSettingsRepositoryImpl(Provider<EntityManager> em) { + public ReviewerDeadlineSettingsRepositoryImpl(Provider<EntityManager> em) { super(em); } diff --git a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerDeadlineSettingsServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerDeadlineSettingsServiceImpl.java index e52d28d078..3f0db387dd 100755 --- a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerDeadlineSettingsServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerDeadlineSettingsServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.reviewing; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import jakarta.inject.Inject; diff --git a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerInteractionServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerInteractionServiceImpl.java index 0079e40a2b..a08f5ffcbc 100644 --- a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerInteractionServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerInteractionServiceImpl.java @@ -1,7 +1,7 @@ package se.su.dsv.scipro.reviewing; import com.google.common.eventbus.EventBus; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.forum.Attachment; import se.su.dsv.scipro.forum.BasicForumService; import se.su.dsv.scipro.forum.dataobjects.ForumPost; diff --git a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerTargetRepositoryImpl.java b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerTargetRepositoryImpl.java index 985ae1934b..ba1b9b961c 100644 --- a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerTargetRepositoryImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerTargetRepositoryImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.reviewing; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import jakarta.persistence.EntityManager; import se.su.dsv.scipro.system.AbstractRepository; import se.su.dsv.scipro.system.User; diff --git a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewingModule.java b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewingModule.java deleted file mode 100644 index 9a0d1d53f7..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewingModule.java +++ /dev/null @@ -1,25 +0,0 @@ -package se.su.dsv.scipro.reviewing; - -import com.google.inject.AbstractModule; -import se.su.dsv.scipro.file.FileService; - -import jakarta.persistence.EntityManager; - -public class ReviewingModule extends AbstractModule { - @Override - protected void configure() { - requireBinding(FileService.class); - requireBinding(EntityManager.class); - bind(ReviewerThreadRepository.class).to(ReviewerThreadRepositoryImpl.class); - bind(ReviewerInteractionService.class).to(ReviewerInteractionServiceImpl.class); - bind(FinalSeminarApprovalService.class).to(FinalSeminarApprovalServiceImpl.class); - bind(MyReviewService.class).to(ReviewingServiceImpl.class); - bind(ReviewerDecisionService.class).to(ReviewingServiceImpl.class); - bind(RoughDraftApprovalService.class).to(RoughDraftApprovalServiceImpl.class); - bind(ReviewerDeadlineSettingsService.class).to(ReviewerDeadlineSettingsServiceImpl.class); - bind(ReviewerDeadlineSettingsRepository.class).to(ReviewerDeadlineSettingsRepositoryImpl.class); - bind(ReviewerDeadlineFollowupService.class).to(ReviewerDeadlineFollowupServiceImpl.class); - bind(ReviewerCapacityService.class).to(ReviewerCapacityServiceImpl.class); - bind(ReviewerAssignmentService.class).to(ReviewerCapacityServiceImpl.class); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/reviewing/RoughDraftApprovalServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/reviewing/RoughDraftApprovalServiceImpl.java index fea26c83d6..f7a4365b24 100644 --- a/core/src/main/java/se/su/dsv/scipro/reviewing/RoughDraftApprovalServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/reviewing/RoughDraftApprovalServiceImpl.java @@ -1,7 +1,7 @@ package se.su.dsv.scipro.reviewing; import com.google.common.eventbus.EventBus; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.file.FileReference; import se.su.dsv.scipro.file.FileService; import se.su.dsv.scipro.file.FileUpload; diff --git a/core/src/main/java/se/su/dsv/scipro/security/auth/AuthenticationModule.java b/core/src/main/java/se/su/dsv/scipro/security/auth/AuthenticationModule.java deleted file mode 100644 index 3598358043..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/security/auth/AuthenticationModule.java +++ /dev/null @@ -1,15 +0,0 @@ -package se.su.dsv.scipro.security.auth; - -import com.google.inject.AbstractModule; -import com.google.inject.multibindings.Multibinder; - -public class AuthenticationModule extends AbstractModule { - @Override - protected void configure() { - bind(AuthenticationService.class).to(AuthenticationServiceImpl.class); - - Multibinder<AuthenticationProvider> authenticationProviders - = Multibinder.newSetBinder(binder(), AuthenticationProvider.class); - authenticationProviders.addBinding().to(LocalAuthentication.class); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/springdata/serviceimpls/UserProfileServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/springdata/serviceimpls/UserProfileServiceImpl.java index a89512dab1..788ae44b07 100644 --- a/core/src/main/java/se/su/dsv/scipro/springdata/serviceimpls/UserProfileServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/springdata/serviceimpls/UserProfileServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.springdata.serviceimpls; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.security.auth.roles.Roles; import se.su.dsv.scipro.settings.dataobjects.QUserProfile; import se.su.dsv.scipro.settings.dataobjects.UserProfile; @@ -43,6 +43,7 @@ public class UserProfileServiceImpl extends AbstractServiceImpl<UserProfile, Lon } @Override + @Transactional public void setSelectedRole(User user, Roles role) { UserProfile profile = findByUser(user); profile.setSelectedRole(role); diff --git a/core/src/main/java/se/su/dsv/scipro/sukat/SukatModule.java b/core/src/main/java/se/su/dsv/scipro/sukat/SukatModule.java deleted file mode 100644 index 544a17ec39..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/sukat/SukatModule.java +++ /dev/null @@ -1,10 +0,0 @@ -package se.su.dsv.scipro.sukat; - -import com.google.inject.AbstractModule; - -public class SukatModule extends AbstractModule { - @Override - protected void configure() { - bind(Sukat.class).to(LDAP.class); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/survey/SurveyModule.java b/core/src/main/java/se/su/dsv/scipro/survey/SurveyModule.java deleted file mode 100644 index 54a6c83c92..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/survey/SurveyModule.java +++ /dev/null @@ -1,17 +0,0 @@ -package se.su.dsv.scipro.survey; - -import com.google.inject.AbstractModule; -import se.su.dsv.scipro.finalthesis.FinalThesisService; - -import jakarta.persistence.EntityManager; - -public class SurveyModule extends AbstractModule { - @Override - protected void configure() { - requireBinding(EntityManager.class); - requireBinding(FinalThesisService.class); - bind(SurveyRepository.class).to(SurveyRepositoryImpl.class); - bind(QuestionRepository.class).to(QuestionRepositoryImpl.class); - bind(SurveyService.class).to(SurveyServiceImpl.class); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/survey/SurveyServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/survey/SurveyServiceImpl.java index ecb7c22070..386c771880 100644 --- a/core/src/main/java/se/su/dsv/scipro/survey/SurveyServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/survey/SurveyServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.survey; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.finalthesis.FinalThesisService; import se.su.dsv.scipro.generalsystemsettings.GeneralSystemSettings; import se.su.dsv.scipro.generalsystemsettings.GeneralSystemSettingsService; diff --git a/core/src/main/java/se/su/dsv/scipro/system/AbstractServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/system/AbstractServiceImpl.java index 748940900e..f6d52a414b 100755 --- a/core/src/main/java/se/su/dsv/scipro/system/AbstractServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/system/AbstractServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.system; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import com.querydsl.core.types.Predicate; import com.querydsl.core.types.dsl.EntityPathBase; import com.querydsl.core.types.dsl.Expressions; diff --git a/core/src/main/java/se/su/dsv/scipro/system/FooterAddressRepo.java b/core/src/main/java/se/su/dsv/scipro/system/FooterAddressRepo.java index ad0f13494d..b326a9c967 100644 --- a/core/src/main/java/se/su/dsv/scipro/system/FooterAddressRepo.java +++ b/core/src/main/java/se/su/dsv/scipro/system/FooterAddressRepo.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.system; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; @Transactional public interface FooterAddressRepo extends JpaRepository<FooterAddress, Long>, QueryDslPredicateExecutor<FooterAddress> { diff --git a/core/src/main/java/se/su/dsv/scipro/system/FooterLinkRepo.java b/core/src/main/java/se/su/dsv/scipro/system/FooterLinkRepo.java index bd0c349289..8994ba19ae 100755 --- a/core/src/main/java/se/su/dsv/scipro/system/FooterLinkRepo.java +++ b/core/src/main/java/se/su/dsv/scipro/system/FooterLinkRepo.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.system; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import java.util.List; import java.util.Optional; diff --git a/core/src/main/java/se/su/dsv/scipro/system/FooterLinkServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/system/FooterLinkServiceImpl.java index 327b83accc..901a487f84 100644 --- a/core/src/main/java/se/su/dsv/scipro/system/FooterLinkServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/system/FooterLinkServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.system; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import jakarta.inject.Inject; import java.util.List; diff --git a/core/src/main/java/se/su/dsv/scipro/system/GenericRepo.java b/core/src/main/java/se/su/dsv/scipro/system/GenericRepo.java index 2a42a60a0e..07ae33135f 100644 --- a/core/src/main/java/se/su/dsv/scipro/system/GenericRepo.java +++ b/core/src/main/java/se/su/dsv/scipro/system/GenericRepo.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.system; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import com.querydsl.core.types.Predicate; import com.querydsl.core.types.dsl.EntityPathBase; import com.querydsl.core.types.dsl.Expressions; diff --git a/core/src/main/java/se/su/dsv/scipro/system/MergeServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/system/MergeServiceImpl.java index 0c58d7f4d5..e14516ffb9 100644 --- a/core/src/main/java/se/su/dsv/scipro/system/MergeServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/system/MergeServiceImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.system; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import jakarta.inject.Inject; diff --git a/core/src/main/java/se/su/dsv/scipro/system/PasswordRepo.java b/core/src/main/java/se/su/dsv/scipro/system/PasswordRepo.java index 32d5c4c4f9..53dfe5d7a8 100755 --- a/core/src/main/java/se/su/dsv/scipro/system/PasswordRepo.java +++ b/core/src/main/java/se/su/dsv/scipro/system/PasswordRepo.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.system; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; @Transactional diff --git a/core/src/main/java/se/su/dsv/scipro/system/UserRepo.java b/core/src/main/java/se/su/dsv/scipro/system/UserRepo.java index 1a227078e1..9831c44da1 100755 --- a/core/src/main/java/se/su/dsv/scipro/system/UserRepo.java +++ b/core/src/main/java/se/su/dsv/scipro/system/UserRepo.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.system; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.security.auth.roles.Roles; import java.util.Collection; diff --git a/core/src/main/java/se/su/dsv/scipro/war/PluginConfiguration.java b/core/src/main/java/se/su/dsv/scipro/war/PluginConfiguration.java new file mode 100644 index 0000000000..a111714130 --- /dev/null +++ b/core/src/main/java/se/su/dsv/scipro/war/PluginConfiguration.java @@ -0,0 +1,4 @@ +package se.su.dsv.scipro.war; + +public interface PluginConfiguration { +} diff --git a/core/src/main/java/se/su/dsv/scipro/workerthreads/AbstractWorker.java b/core/src/main/java/se/su/dsv/scipro/workerthreads/AbstractWorker.java index 751b6c8831..5c721b2ffe 100755 --- a/core/src/main/java/se/su/dsv/scipro/workerthreads/AbstractWorker.java +++ b/core/src/main/java/se/su/dsv/scipro/workerthreads/AbstractWorker.java @@ -1,6 +1,5 @@ package se.su.dsv.scipro.workerthreads; -import com.google.inject.persist.UnitOfWork; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,9 +22,7 @@ public abstract class AbstractWorker implements Worker { private WorkerData wd = null; private Date lastSuccessfulRun = new Date(0); private boolean successfulWorker = true; - private Provider<EntityManager> emProvider; - private EntityTransaction transaction; - private UnitOfWork unitOfWork; + private WorkerTransactionManager txManager; /** * Subclasses must be annotated with @Component or similar annotation in order for autowiring of dependencies to work @@ -39,22 +36,13 @@ public abstract class AbstractWorker implements Worker { } @Inject - public void setTxManager(Provider<EntityManager> em) { - this.emProvider = em; - } - - @Inject - public void setUnitOfWork(UnitOfWork unitOfWork) { - this.unitOfWork = unitOfWork; + public void setTxManager(WorkerTransactionManager txManager) { + this.txManager = txManager; } @Override public void run() { - unitOfWork.begin(); - EntityManager em = emProvider.get(); try { - transaction = em.getTransaction(); - wd = workerDataService.getWorkerDataByName(getName()); if (wd != null) { lastSuccessfulRun = wd.getLastSuccessfulRun(); @@ -80,9 +68,7 @@ public abstract class AbstractWorker implements Worker { setSuccessfulWorker(false); } finally { - if (transaction.isActive() && em.isOpen()) { - transaction.rollback(); - } + txManager.rollbackIfActive(); } // in case a job crashes or clears the cache (so the entity is detached) @@ -95,10 +81,7 @@ public abstract class AbstractWorker implements Worker { saveWorkerData(); } finally { - if (transaction.isActive() && em.isOpen()) { - transaction.rollback(); - } - unitOfWork.end(); + txManager.rollbackIfActive(); } } @@ -148,15 +131,15 @@ public abstract class AbstractWorker implements Worker { protected abstract void doWork(); protected void beginTransaction() { - transaction.begin(); + txManager.begin(); } protected void commitTransaction() { - transaction.commit(); + txManager.commit(); } protected void rollbackTransaction() { - transaction.rollback(); + txManager.rollback(); } } diff --git a/core/src/main/java/se/su/dsv/scipro/workerthreads/WorkerModule.java b/core/src/main/java/se/su/dsv/scipro/workerthreads/WorkerModule.java deleted file mode 100644 index 370d486d83..0000000000 --- a/core/src/main/java/se/su/dsv/scipro/workerthreads/WorkerModule.java +++ /dev/null @@ -1,31 +0,0 @@ -package se.su.dsv.scipro.workerthreads; - -import com.google.inject.AbstractModule; -import com.google.inject.Scopes; -import com.google.inject.multibindings.Multibinder; -import se.su.dsv.scipro.mail.MailEventWorker; -import se.su.dsv.scipro.projectpartner.RemoveFulfilledPartnerAdsWorker; -import se.su.dsv.scipro.system.Lifecycle; - -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; - -public class WorkerModule extends AbstractModule { - private static final int NUMBER_OF_WORKER_THREADS = 4; - - @Override - protected void configure() { - Multibinder.newSetBinder(binder(), Lifecycle.class).addBinding().to(SchedulerImpl.class); - bind(ScheduledExecutorService.class).toInstance(Executors.newScheduledThreadPool(NUMBER_OF_WORKER_THREADS)); - bind(Scheduler.class).to(SchedulerImpl.class).in(Scopes.SINGLETON); - bind(TemporaryWorkerScheduler.class).asEagerSingleton(); - bind(WorkerDataService.class).to(WorkerDataServiceImpl.class); - bind(ThesisUploadDeadlineWorker.class); - bind(ManualMatchRemindWorker.class); - bind(MailEventWorker.class); - bind(NotificationCompilationWorker.class); - bind(ThesisUploadReminderWorker.class); - bind(IdeaExportWorker.class); - bind(RemoveFulfilledPartnerAdsWorker.class); - } -} diff --git a/core/src/main/java/se/su/dsv/scipro/workerthreads/WorkerTransactionManager.java b/core/src/main/java/se/su/dsv/scipro/workerthreads/WorkerTransactionManager.java new file mode 100644 index 0000000000..1ff2b458d4 --- /dev/null +++ b/core/src/main/java/se/su/dsv/scipro/workerthreads/WorkerTransactionManager.java @@ -0,0 +1,20 @@ +package se.su.dsv.scipro.workerthreads; + +public interface WorkerTransactionManager { + void rollbackIfActive(); + + /** + * @throws IllegalStateException if a transaction is already active + */ + void begin(); + + /** + * @throws IllegalStateException if a transaction is not active + */ + void commit(); + + /** + * @throws IllegalStateException if a transaction is not active + */ + void rollback(); +} diff --git a/core/src/test/java/se/su/dsv/scipro/forum/ForumModuleTest.java b/core/src/test/java/se/su/dsv/scipro/forum/ForumModuleTest.java index 4c0f37379d..90cc242e77 100644 --- a/core/src/test/java/se/su/dsv/scipro/forum/ForumModuleTest.java +++ b/core/src/test/java/se/su/dsv/scipro/forum/ForumModuleTest.java @@ -1,20 +1,15 @@ package se.su.dsv.scipro.forum; -import com.google.inject.AbstractModule; -import com.google.inject.Module; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import se.su.dsv.scipro.date.DateService; -import se.su.dsv.scipro.file.FileModule; -import se.su.dsv.scipro.file.FileStore; import se.su.dsv.scipro.notifications.NotificationController; import se.su.dsv.scipro.notifications.NotificationService; -import se.su.dsv.scipro.test.GuiceTest; -import se.su.dsv.scipro.test.InMemoryFileStore; +import se.su.dsv.scipro.test.SpringTest; @ExtendWith(MockitoExtension.class) -public abstract class ForumModuleTest extends GuiceTest { +public abstract class ForumModuleTest extends SpringTest { // TODO: Work towards removing these dependencies. @Mock private DateService dateService; @@ -23,18 +18,4 @@ public abstract class ForumModuleTest extends GuiceTest { @Mock private NotificationService notificationService; - @Override - protected Module moduleUnderTest() { - return new AbstractModule() { - @Override - protected void configure() { - install(new ForumModule()); - install(new FileModule()); - bind(FileStore.class).to(InMemoryFileStore.class); - bind(DateService.class).toInstance(dateService); - bind(NotificationController.class).toInstance(notificationController); - bind(NotificationService.class).toInstance(notificationService); - } - }; - } } diff --git a/core/src/test/java/se/su/dsv/scipro/group/GroupServiceImplTest.java b/core/src/test/java/se/su/dsv/scipro/group/GroupServiceImplTest.java index da314ab9c1..4a3e6dc33c 100644 --- a/core/src/test/java/se/su/dsv/scipro/group/GroupServiceImplTest.java +++ b/core/src/test/java/se/su/dsv/scipro/group/GroupServiceImplTest.java @@ -1,135 +1,135 @@ -package se.su.dsv.scipro.group; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import se.su.dsv.scipro.project.Project; -import se.su.dsv.scipro.system.DegreeType; -import se.su.dsv.scipro.system.ProjectType; -import se.su.dsv.scipro.system.User; -import se.su.dsv.scipro.test.IntegrationTest; - -import jakarta.inject.Inject; -import java.time.LocalDate; -import java.util.Collections; -import java.util.HashSet; - -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.hasItem; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class GroupServiceImplTest extends IntegrationTest { - - @Inject - private GroupServiceImpl groupService; - private User author; - private User creator; - private User reviewer; - private User cosupervisor; - private Group group; - private ProjectType projectType; - - @BeforeEach - public void setUp() throws Exception { - author = saveUser("author", "name", "author@example.com"); - creator = saveUser("supervisor", "sup", "supervisor@example.com"); - reviewer = saveUser("reviewer", "test", "reviewer@example.com"); - cosupervisor = saveUser("cosupervisor", "test", "reviewer@example.com"); - projectType = save(new ProjectType(DegreeType.BACHELOR, "b", "b")); - User headSupervisor = save(User.builder().firstName("John").lastName("Doe").emailAddress("john@example.com").build()); - Project project = save(Project.builder().title("title").projectType(projectType).startDate(LocalDate.now()).headSupervisor(headSupervisor).build()); - project.addProjectParticipant(author); - project.addReviewer(reviewer); - project.addCoSupervisor(cosupervisor); - createGroup(project); - } - - @Test - public void find_by_author() { - GroupService.Filter filter = new GroupService.Filter(); - filter.setAuthor(author); - assertGroup(filter); - } - - @Test - public void find_all() { - GroupService.Filter filter = new GroupService.Filter(); - assertGroup(filter); - } - - @Test - public void find_by_creator_fails() { - GroupService.Filter filter = new GroupService.Filter(); - filter.setCreator(author); - assertTrue(groupService.findAll(filter).isEmpty()); - } - - @Test - public void find_by_creator() { - GroupService.Filter filter = new GroupService.Filter(); - filter.setCreator(creator); - assertGroup(filter); - } - - @Test - public void find_by_reviewer_involvee() { - GroupService.Filter filter = new GroupService.Filter(); - filter.setNonAuthorInvolvee(reviewer); - assertThat(groupService.findAll(filter), not(hasItem(group))); - } - - @Test - public void find_by_cosupervisor_involvee() { - GroupService.Filter filter = new GroupService.Filter(); - filter.setNonAuthorInvolvee(cosupervisor); - assertGroup(filter); - } - - @Test - public void find_active_groups() { - GroupService.Filter filter = new GroupService.Filter(); - filter.setActive(true); - assertGroup(filter); - - filter.setActive(false); - assertTrue(groupService.findAll(filter).isEmpty()); - } - - @Test - public void count() { - GroupService.Filter filter = new GroupService.Filter(); - filter.setAuthor(author); - assertEquals(1, groupService.count(filter)); - } - - @Test - public void find_groups_by_project() { - Group another = new Group(); - another.setTitle("hi"); - another.setUser(creator); - User headSupervisor = save(User.builder().firstName("John").lastName("Doe").emailAddress("john@example.com").build()); - Project anotherProject = save(Project.builder().title("another").projectType(projectType).startDate(LocalDate.now()).headSupervisor(headSupervisor).build()); - another.setProjects(new HashSet<>(Collections.singletonList(anotherProject))); - save(another); - GroupService.Filter filter = new GroupService.Filter(); - filter.setProject(anotherProject); - assertEquals(another, groupService.findAll(filter).get(0)); - } - - private void assertGroup(GroupService.Filter filter) { - assertThat(groupService.findAll(filter), hasItem(group)); - } - - private void createGroup(Project project) { - group = new Group(); - group.setTitle("group title"); - group.setProjects(new HashSet<>(Collections.singletonList(project))); - group.setUser(creator); - save(group); - } - - private User saveUser(String firstName, String lastName, String emailAddress) { - return save(User.builder().firstName(firstName).lastName(lastName).emailAddress(emailAddress).build()); - } -} +package se.su.dsv.scipro.group; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import se.su.dsv.scipro.project.Project; +import se.su.dsv.scipro.system.DegreeType; +import se.su.dsv.scipro.system.ProjectType; +import se.su.dsv.scipro.system.User; +import se.su.dsv.scipro.test.IntegrationTest; + +import jakarta.inject.Inject; +import java.time.LocalDate; +import java.util.Collections; +import java.util.HashSet; + +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItem; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class GroupServiceImplTest extends IntegrationTest { + + @Inject + private GroupServiceImpl groupService; + private User author; + private User creator; + private User reviewer; + private User cosupervisor; + private Group group; + private ProjectType projectType; + + @BeforeEach + public void setUp() throws Exception { + author = saveUser("author", "name", "author@example.com"); + creator = saveUser("supervisor", "sup", "supervisor@example.com"); + reviewer = saveUser("reviewer", "test", "reviewer@example.com"); + cosupervisor = saveUser("cosupervisor", "test", "reviewer@example.com"); + projectType = save(new ProjectType(DegreeType.BACHELOR, "b", "b")); + User headSupervisor = save(User.builder().firstName("John").lastName("Doe").emailAddress("john@example.com").build()); + Project project = save(Project.builder().title("title").projectType(projectType).startDate(LocalDate.now()).headSupervisor(headSupervisor).build()); + project.addProjectParticipant(author); + project.addReviewer(reviewer); + project.addCoSupervisor(cosupervisor); + createGroup(project); + } + + @Test + public void find_by_author() { + GroupService.Filter filter = new GroupService.Filter(); + filter.setAuthor(author); + assertGroup(filter); + } + + @Test + public void find_all() { + GroupService.Filter filter = new GroupService.Filter(); + assertGroup(filter); + } + + @Test + public void find_by_creator_fails() { + GroupService.Filter filter = new GroupService.Filter(); + filter.setCreator(author); + assertTrue(groupService.findAll(filter).isEmpty()); + } + + @Test + public void find_by_creator() { + GroupService.Filter filter = new GroupService.Filter(); + filter.setCreator(creator); + assertGroup(filter); + } + + @Test + public void find_by_reviewer_involvee() { + GroupService.Filter filter = new GroupService.Filter(); + filter.setNonAuthorInvolvee(reviewer); + assertThat(groupService.findAll(filter), not(hasItem(group))); + } + + @Test + public void find_by_cosupervisor_involvee() { + GroupService.Filter filter = new GroupService.Filter(); + filter.setNonAuthorInvolvee(cosupervisor); + assertGroup(filter); + } + + @Test + public void find_active_groups() { + GroupService.Filter filter = new GroupService.Filter(); + filter.setActive(true); + assertGroup(filter); + + filter.setActive(false); + assertTrue(groupService.findAll(filter).isEmpty()); + } + + @Test + public void count() { + GroupService.Filter filter = new GroupService.Filter(); + filter.setAuthor(author); + assertEquals(1, groupService.count(filter)); + } + + @Test + public void find_groups_by_project() { + Group another = new Group(); + another.setTitle("hi"); + another.setUser(creator); + User headSupervisor = save(User.builder().firstName("John").lastName("Doe").emailAddress("john@example.com").build()); + Project anotherProject = save(Project.builder().title("another").projectType(projectType).startDate(LocalDate.now()).headSupervisor(headSupervisor).build()); + another.setProjects(new HashSet<>(Collections.singletonList(anotherProject))); + save(another); + GroupService.Filter filter = new GroupService.Filter(); + filter.setProject(anotherProject); + assertEquals(another, groupService.findAll(filter).get(0)); + } + + private void assertGroup(GroupService.Filter filter) { + assertThat(groupService.findAll(filter), hasItem(group)); + } + + private void createGroup(Project project) { + group = new Group(); + group.setTitle("group title"); + group.setProjects(new HashSet<>(Collections.singletonList(project))); + group.setUser(creator); + save(group); + } + + private User saveUser(String firstName, String lastName, String emailAddress) { + return save(User.builder().firstName(firstName).lastName(lastName).emailAddress(emailAddress).build()); + } +} diff --git a/core/src/test/java/se/su/dsv/scipro/match/MatchModuleTest.java b/core/src/test/java/se/su/dsv/scipro/match/MatchModuleTest.java index 63417a754b..7a189d32f4 100644 --- a/core/src/test/java/se/su/dsv/scipro/match/MatchModuleTest.java +++ b/core/src/test/java/se/su/dsv/scipro/match/MatchModuleTest.java @@ -1,9 +1,6 @@ package se.su.dsv.scipro.match; import com.google.common.eventbus.EventBus; -import com.google.inject.AbstractModule; -import com.google.inject.Module; -import com.google.inject.name.Names; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -13,10 +10,10 @@ import se.su.dsv.scipro.generalsystemsettings.GeneralSystemSettingsService; import se.su.dsv.scipro.mail.MailEventService; import se.su.dsv.scipro.notifications.NotificationController; import se.su.dsv.scipro.project.ProjectService; -import se.su.dsv.scipro.test.GuiceTest; +import se.su.dsv.scipro.test.SpringTest; @ExtendWith(MockitoExtension.class) -public abstract class MatchModuleTest extends GuiceTest { +public abstract class MatchModuleTest extends SpringTest { // ToDo:The system services should be move to a system module that other modules can depend on @Mock protected DateService dateService; @@ -34,28 +31,4 @@ public abstract class MatchModuleTest extends GuiceTest { @Mock protected ProjectService projectService; - @Override - protected Module moduleUnderTest() { - return new AbstractModule() { - @Override - protected void configure() { - install(new MatchModule()); - bind(GeneralSystemSettingsService.class).toInstance(generalSystemSettingsService); - bind(NotificationController.class).toInstance(notificationController); - bind(DateService.class).toInstance(dateService); - bind(MailEventService.class).toInstance(mailEventService); - bind(ActivityPlanFacade.class).toInstance(activityPlanFacade); - bind(EventBus.class).toInstance(eventBus); - bind(ProjectService.class).toInstance(projectService); - - // Work towards removing the dependency on NotificationSourceURL - bindConstant().annotatedWith(Names.named("source.export.fail.supervisor")).to(""); - bindConstant().annotatedWith(Names.named("source.export.fail.user")).to(""); - bindConstant().annotatedWith(Names.named("source.export.success.supervisor")).to(""); - bindConstant().annotatedWith(Names.named("source.export.success.user")).to(""); - bindConstant().annotatedWith(Names.named("source.project.supervisor")).to(""); - bindConstant().annotatedWith(Names.named("source.project.student")).to(""); - } - }; - } } diff --git a/core/src/test/java/se/su/dsv/scipro/notifications/NotificationControllerImplTest.java b/core/src/test/java/se/su/dsv/scipro/notifications/NotificationControllerImplTest.java index 6453a0f537..6c770e1a9d 100755 --- a/core/src/test/java/se/su/dsv/scipro/notifications/NotificationControllerImplTest.java +++ b/core/src/test/java/se/su/dsv/scipro/notifications/NotificationControllerImplTest.java @@ -1,6 +1,5 @@ package se.su.dsv.scipro.notifications; -import com.google.inject.util.Providers; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; @@ -55,7 +54,7 @@ public class NotificationControllerImplTest { notificationService, mailFormatter, mailEventService, - receiverConfiguration, deliveryConfiguration, Providers.of(currentUser)); + receiverConfiguration, deliveryConfiguration, () -> currentUser); when(mailFormatter.format(isA(Notification.class))).thenReturn(new NotificationMail("Subject", "Body")); when(deliveryConfiguration.isDelivery(isA(Notification.Type.class), isA(Enum.class), isA(DeliveryMethod.class), isA(Optional.class))).thenReturn(true); diff --git a/core/src/test/java/se/su/dsv/scipro/plagiarism/urkund/UrkundSettingsRepositoryTest.java b/core/src/test/java/se/su/dsv/scipro/plagiarism/urkund/UrkundSettingsRepositoryTest.java index a2eb62c871..8b113e1524 100644 --- a/core/src/test/java/se/su/dsv/scipro/plagiarism/urkund/UrkundSettingsRepositoryTest.java +++ b/core/src/test/java/se/su/dsv/scipro/plagiarism/urkund/UrkundSettingsRepositoryTest.java @@ -1,35 +1,16 @@ package se.su.dsv.scipro.plagiarism.urkund; -import com.google.inject.AbstractModule; -import com.google.inject.Module; import org.junit.jupiter.api.Test; -import se.su.dsv.scipro.file.FileModule; -import se.su.dsv.scipro.file.FileStore; -import se.su.dsv.scipro.sukat.SukatModule; -import se.su.dsv.scipro.test.GuiceTest; -import se.su.dsv.scipro.test.InMemoryFileStore; +import se.su.dsv.scipro.test.SpringTest; import jakarta.inject.Inject; import static org.junit.jupiter.api.Assertions.assertEquals; -public class UrkundSettingsRepositoryTest extends GuiceTest { +public class UrkundSettingsRepositoryTest extends SpringTest { @Inject private UrkundSettingsRepository urkundSettingsRepository; - @Override - protected Module moduleUnderTest() { - return new AbstractModule() { - @Override - protected void configure() { - install(new SukatModule()); - install(new UrkundModule()); - install(new FileModule()); - bind(FileStore.class).to(InMemoryFileStore.class); - } - }; - } - @Test public void change_settings() { final UrkundSettings settings = urkundSettingsRepository.getSettings(); diff --git a/core/src/test/java/se/su/dsv/scipro/plagiarism/urkund/UrkundSubmissionRepositoryTest.java b/core/src/test/java/se/su/dsv/scipro/plagiarism/urkund/UrkundSubmissionRepositoryTest.java index 0d2599f5fd..6120fe3468 100644 --- a/core/src/test/java/se/su/dsv/scipro/plagiarism/urkund/UrkundSubmissionRepositoryTest.java +++ b/core/src/test/java/se/su/dsv/scipro/plagiarism/urkund/UrkundSubmissionRepositoryTest.java @@ -1,18 +1,12 @@ package se.su.dsv.scipro.plagiarism.urkund; -import com.google.inject.AbstractModule; -import com.google.inject.Module; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; import org.junit.jupiter.api.Test; import se.su.dsv.scipro.file.FileDescription; -import se.su.dsv.scipro.file.FileModule; import se.su.dsv.scipro.file.FileReference; -import se.su.dsv.scipro.file.FileStore; -import se.su.dsv.scipro.sukat.Sukat; -import se.su.dsv.scipro.test.GuiceTest; -import se.su.dsv.scipro.test.InMemoryFileStore; +import se.su.dsv.scipro.test.SpringTest; import jakarta.inject.Inject; import java.time.Instant; @@ -22,23 +16,10 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; -public class UrkundSubmissionRepositoryTest extends GuiceTest { +public class UrkundSubmissionRepositoryTest extends SpringTest { @Inject private UrkundSubmissionRepository submissionRepository; - - @Override - protected Module moduleUnderTest() { - return new AbstractModule() { - @Override - protected void configure() { - install(new UrkundModule()); - bind(Sukat.class).toInstance((username) -> Optional.empty()); - install(new FileModule()); - bind(FileStore.class).to(InMemoryFileStore.class); - } - }; - } @Test public void save() { diff --git a/core/src/test/java/se/su/dsv/scipro/reviewing/ReviewingModuleTest.java b/core/src/test/java/se/su/dsv/scipro/reviewing/ReviewingModuleTest.java index 8d59c17234..ba058fcce1 100644 --- a/core/src/test/java/se/su/dsv/scipro/reviewing/ReviewingModuleTest.java +++ b/core/src/test/java/se/su/dsv/scipro/reviewing/ReviewingModuleTest.java @@ -1,18 +1,6 @@ package se.su.dsv.scipro.reviewing; -import com.google.inject.AbstractModule; -import com.google.inject.Module; import se.su.dsv.scipro.test.IntegrationTest; public abstract class ReviewingModuleTest extends IntegrationTest { - @Override - protected Module moduleUnderTest() { - return new AbstractModule() { - @Override - protected void configure() { - install(ReviewingModuleTest.super.moduleUnderTest()); - bind(ReviewerAssignedDeadline.class).asEagerSingleton(); - } - }; - } } diff --git a/core/src/test/java/se/su/dsv/scipro/reviewing/ReviewingServiceImplTest.java b/core/src/test/java/se/su/dsv/scipro/reviewing/ReviewingServiceImplTest.java index 56398d9f29..dd4ad1a076 100644 --- a/core/src/test/java/se/su/dsv/scipro/reviewing/ReviewingServiceImplTest.java +++ b/core/src/test/java/se/su/dsv/scipro/reviewing/ReviewingServiceImplTest.java @@ -1,161 +1,161 @@ -package se.su.dsv.scipro.reviewing; - -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentMatchers; -import se.su.dsv.scipro.file.FileUpload; -import se.su.dsv.scipro.project.Project; -import se.su.dsv.scipro.system.DegreeType; -import se.su.dsv.scipro.system.Page; -import se.su.dsv.scipro.system.ProjectType; -import se.su.dsv.scipro.system.User; -import se.su.dsv.scipro.util.Either; - -import jakarta.inject.Inject; -import java.time.LocalDate; -import java.util.List; -import java.util.Optional; -import java.util.function.Function; - -import static org.hamcrest.CoreMatchers.hasItem; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.instanceOf; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class ReviewingServiceImplTest extends ReviewingModuleTest { - private static final TestPage ALL = new TestPage(0, Long.MAX_VALUE); - - @Inject - private ReviewingServiceImpl reviewingService; - @Inject - private FinalSeminarApprovalServiceImpl finalSeminarApprovalService; - @Inject - private RoughDraftApprovalServiceImpl roughDraftApprovalService; - - private Project project; - private User reviewer; - private Project project3; - - @BeforeEach - public void setUp() throws Exception { - reviewer = save(User.builder().firstName("Ronny").lastName("Reviewer").emailAddress("reviewer@dsv.su.se").build()); - User reviewer2 = save(User.builder().firstName("Ronny").lastName("Reviewer").emailAddress("reviewer@dsv.su.se").build()); - User headSupervisor = save(User.builder().firstName("John").lastName("Doe").emailAddress("john@example.com").build()); - ProjectType bachelor = save(new ProjectType(DegreeType.BACHELOR, "Bachelor", "Bachelor")); - project = save(Project.builder().title("My project").projectType(bachelor).startDate(LocalDate.now()).headSupervisor(headSupervisor).build()); - project.addReviewer(reviewer); - Project project2 = save(Project.builder().title("My project 2").projectType(bachelor).startDate(LocalDate.now()).headSupervisor(headSupervisor).build()); - project2.addReviewer(reviewer2); - project3 = save(Project.builder().title("My project 3").projectType(bachelor).startDate(LocalDate.now()).headSupervisor(headSupervisor).build()); - project3.addReviewer(reviewer); - } - - @Test - public void count() { - finalSeminarApprovalService.requestApproval(project, createFileUpload(), "test"); - assertEquals(1, reviewingService.countDecisions(getFilter(ReviewerApproval.Step.FINAL_SEMINAR_APPROVAL))); - } - - private MyReviewService.Filter getFilter(ReviewerApproval.Step step) { - MyReviewService.Filter filter = new MyReviewService.Filter(); - filter.setUser(reviewer); - filter.setStep(step); - return filter; - } - - @Test - public void find_undecided() { - finalSeminarApprovalService.requestApproval(project, createFileUpload(), "test"); - assertThat(reviewingService.findAllDecisions(getFilter(ReviewerApproval.Step.FINAL_SEMINAR_APPROVAL), ALL), hasItem(where(Decision::getReviewerApproval, instanceOf(FinalSeminarApproval.class)))); - } - - @Test - public void find_undecided_rough_draft_approvals() { - roughDraftApprovalService.requestApproval(project, createFileUpload(), "test"); - assertThat(reviewingService.findAllDecisions(getFilter(ReviewerApproval.Step.ROUGH_DRAFT_APPROVAL), ALL), hasItem(where(Decision::getReviewerApproval, instanceOf(RoughDraftApproval.class)))); - } - - @Test - public void count_undecided_rough_drafts() { - roughDraftApprovalService.requestApproval(project, createFileUpload(), "test"); - assertEquals(reviewingService.countUndecidedRoughDraft(reviewer), 1); - } - - @Test - public void back_and_forth() { - assertTrue(finalSeminarApprovalService.requiresUpload(project)); - Either<AlreadyRequested, FinalSeminarApproval> first = finalSeminarApprovalService.requestApproval(project, createFileUpload(), "test"); - assertFalse(finalSeminarApprovalService.requiresUpload(project)); - - first.foreach(firstFinalSeminarApproval -> reviewingService.reject(firstFinalSeminarApproval, "Very bad", Optional.of(createFileUpload()))); - - assertTrue(finalSeminarApprovalService.requiresUpload(project)); - Either<AlreadyRequested, FinalSeminarApproval> second = finalSeminarApprovalService.requestApproval(project, createFileUpload(), "test"); - assertFalse(finalSeminarApprovalService.requiresUpload(project)); - - second.foreach(secondFinalSeminarApproval -> reviewingService.approve(secondFinalSeminarApproval, "Very good", Optional.empty())); - assertFalse(finalSeminarApprovalService.requiresUpload(project)); - } - - @Test - public void only_fetches_my_reviews() { - Either<AlreadyRequested, RoughDraftApproval> myRequest = - roughDraftApprovalService.requestApproval(project, createFileUpload(), "my request"); - assertTrue(myRequest.isRight()); - - List<Decision> requests = reviewingService.findAllDecisions(getFilter(ReviewerApproval.Step.ROUGH_DRAFT_APPROVAL), ALL); - assertEquals(1, requests.size()); - } - - @Test - public void sort_by_requested() { - Either<AlreadyRequested, RoughDraftApproval> request1 = - roughDraftApprovalService.requestApproval(project, createFileUpload(), "request 1"); - assertTrue(request1.isRight()); - - Either<AlreadyRequested, RoughDraftApproval> request2 = - roughDraftApprovalService.requestApproval(project3, createFileUpload(), "request 2"); - assertTrue(request2.isRight()); - - var sortByRequested = new Page.Sort<>(MyReviewService.Sort.TITLE, Page.Direction.DESCENDING); - TestPage page = new TestPage(0, Long.MAX_VALUE, sortByRequested); - List<Decision> requests = - reviewingService.findAllDecisions(getFilter(ReviewerApproval.Step.ROUGH_DRAFT_APPROVAL), page); - - assertEquals(2, requests.size()); - assertEquals(request2.right(), requests.get(0).getReviewerApproval()); - assertEquals(request1.right(), requests.get(1).getReviewerApproval()); - } - - private FileUpload createFileUpload() { - FileUpload fileUpload = mock(FileUpload.class); - when(fileUpload.handleData(ArgumentMatchers.any())).thenReturn(null); - return fileUpload; - } - - record TestPage(long offset, long limit, Sort<MyReviewService.Sort> sort) implements Page<MyReviewService.Sort> { - TestPage(long offset, long limit) { - this(offset, limit, new Sort<>(MyReviewService.Sort.TITLE, Direction.ASCENDING)); - } - } - - private static <A, B> Matcher<A> where(Function<A, B> f, Matcher<? extends B> matcher) { - return new TypeSafeMatcher<>() { - @Override - protected boolean matchesSafely(A a) { - return matcher.matches(f.apply(a)); - } - - @Override - public void describeTo(Description description) { - description.appendText("an object where ") - .appendDescriptionOf(matcher); - } - }; - } -} +package se.su.dsv.scipro.reviewing; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentMatchers; +import se.su.dsv.scipro.file.FileUpload; +import se.su.dsv.scipro.project.Project; +import se.su.dsv.scipro.system.DegreeType; +import se.su.dsv.scipro.system.Page; +import se.su.dsv.scipro.system.ProjectType; +import se.su.dsv.scipro.system.User; +import se.su.dsv.scipro.util.Either; + +import jakarta.inject.Inject; +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ReviewingServiceImplTest extends ReviewingModuleTest { + private static final TestPage ALL = new TestPage(0, Long.MAX_VALUE); + + @Inject + private ReviewingServiceImpl reviewingService; + @Inject + private FinalSeminarApprovalServiceImpl finalSeminarApprovalService; + @Inject + private RoughDraftApprovalServiceImpl roughDraftApprovalService; + + private Project project; + private User reviewer; + private Project project3; + + @BeforeEach + public void setUp() throws Exception { + reviewer = save(User.builder().firstName("Ronny").lastName("Reviewer").emailAddress("reviewer@dsv.su.se").build()); + User reviewer2 = save(User.builder().firstName("Ronny").lastName("Reviewer").emailAddress("reviewer@dsv.su.se").build()); + User headSupervisor = save(User.builder().firstName("John").lastName("Doe").emailAddress("john@example.com").build()); + ProjectType bachelor = save(new ProjectType(DegreeType.BACHELOR, "Bachelor", "Bachelor")); + project = save(Project.builder().title("My project").projectType(bachelor).startDate(LocalDate.now()).headSupervisor(headSupervisor).build()); + project.addReviewer(reviewer); + Project project2 = save(Project.builder().title("My project 2").projectType(bachelor).startDate(LocalDate.now()).headSupervisor(headSupervisor).build()); + project2.addReviewer(reviewer2); + project3 = save(Project.builder().title("My project 3").projectType(bachelor).startDate(LocalDate.now()).headSupervisor(headSupervisor).build()); + project3.addReviewer(reviewer); + } + + @Test + public void count() { + finalSeminarApprovalService.requestApproval(project, createFileUpload(), "test"); + assertEquals(1, reviewingService.countDecisions(getFilter(ReviewerApproval.Step.FINAL_SEMINAR_APPROVAL))); + } + + private MyReviewService.Filter getFilter(ReviewerApproval.Step step) { + MyReviewService.Filter filter = new MyReviewService.Filter(); + filter.setUser(reviewer); + filter.setStep(step); + return filter; + } + + @Test + public void find_undecided() { + finalSeminarApprovalService.requestApproval(project, createFileUpload(), "test"); + assertThat(reviewingService.findAllDecisions(getFilter(ReviewerApproval.Step.FINAL_SEMINAR_APPROVAL), ALL), hasItem(where(Decision::getReviewerApproval, instanceOf(FinalSeminarApproval.class)))); + } + + @Test + public void find_undecided_rough_draft_approvals() { + roughDraftApprovalService.requestApproval(project, createFileUpload(), "test"); + assertThat(reviewingService.findAllDecisions(getFilter(ReviewerApproval.Step.ROUGH_DRAFT_APPROVAL), ALL), hasItem(where(Decision::getReviewerApproval, instanceOf(RoughDraftApproval.class)))); + } + + @Test + public void count_undecided_rough_drafts() { + roughDraftApprovalService.requestApproval(project, createFileUpload(), "test"); + assertEquals(reviewingService.countUndecidedRoughDraft(reviewer), 1); + } + + @Test + public void back_and_forth() { + assertTrue(finalSeminarApprovalService.requiresUpload(project)); + Either<AlreadyRequested, FinalSeminarApproval> first = finalSeminarApprovalService.requestApproval(project, createFileUpload(), "test"); + assertFalse(finalSeminarApprovalService.requiresUpload(project)); + + first.foreach(firstFinalSeminarApproval -> reviewingService.reject(firstFinalSeminarApproval, "Very bad", Optional.of(createFileUpload()))); + + assertTrue(finalSeminarApprovalService.requiresUpload(project)); + Either<AlreadyRequested, FinalSeminarApproval> second = finalSeminarApprovalService.requestApproval(project, createFileUpload(), "test"); + assertFalse(finalSeminarApprovalService.requiresUpload(project)); + + second.foreach(secondFinalSeminarApproval -> reviewingService.approve(secondFinalSeminarApproval, "Very good", Optional.empty())); + assertFalse(finalSeminarApprovalService.requiresUpload(project)); + } + + @Test + public void only_fetches_my_reviews() { + Either<AlreadyRequested, RoughDraftApproval> myRequest = + roughDraftApprovalService.requestApproval(project, createFileUpload(), "my request"); + assertTrue(myRequest.isRight()); + + List<Decision> requests = reviewingService.findAllDecisions(getFilter(ReviewerApproval.Step.ROUGH_DRAFT_APPROVAL), ALL); + assertEquals(1, requests.size()); + } + + @Test + public void sort_by_requested() { + Either<AlreadyRequested, RoughDraftApproval> request1 = + roughDraftApprovalService.requestApproval(project, createFileUpload(), "request 1"); + assertTrue(request1.isRight()); + + Either<AlreadyRequested, RoughDraftApproval> request2 = + roughDraftApprovalService.requestApproval(project3, createFileUpload(), "request 2"); + assertTrue(request2.isRight()); + + var sortByRequested = new Page.Sort<>(MyReviewService.Sort.TITLE, Page.Direction.DESCENDING); + TestPage page = new TestPage(0, Long.MAX_VALUE, sortByRequested); + List<Decision> requests = + reviewingService.findAllDecisions(getFilter(ReviewerApproval.Step.ROUGH_DRAFT_APPROVAL), page); + + assertEquals(2, requests.size()); + assertEquals(request2.right(), requests.get(0).getReviewerApproval()); + assertEquals(request1.right(), requests.get(1).getReviewerApproval()); + } + + private FileUpload createFileUpload() { + FileUpload fileUpload = mock(FileUpload.class); + when(fileUpload.handleData(ArgumentMatchers.any())).thenReturn(null); + return fileUpload; + } + + record TestPage(long offset, long limit, Sort<MyReviewService.Sort> sort) implements Page<MyReviewService.Sort> { + TestPage(long offset, long limit) { + this(offset, limit, new Sort<>(MyReviewService.Sort.TITLE, Direction.ASCENDING)); + } + } + + private static <A, B> Matcher<A> where(Function<A, B> f, Matcher<? extends B> matcher) { + return new TypeSafeMatcher<>() { + @Override + protected boolean matchesSafely(A a) { + return matcher.matches(f.apply(a)); + } + + @Override + public void describeTo(Description description) { + description.appendText("an object where ") + .appendDescriptionOf(matcher); + } + }; + } +} diff --git a/core/src/test/java/se/su/dsv/scipro/test/GuiceTest.java b/core/src/test/java/se/su/dsv/scipro/test/GuiceTest.java deleted file mode 100644 index 6d2667ef5c..0000000000 --- a/core/src/test/java/se/su/dsv/scipro/test/GuiceTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package se.su.dsv.scipro.test; - -import com.google.inject.AbstractModule; -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.google.inject.Module; -import com.google.inject.persist.PersistService; -import com.google.inject.persist.UnitOfWork; -import com.google.inject.persist.jpa.JpaPersistModule; -import jakarta.persistence.EntityManager; -import jakarta.persistence.EntityTransaction; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; - -import jakarta.inject.Inject; -import jakarta.inject.Provider; -import java.time.Clock; - -public abstract class GuiceTest { - @Inject - private UnitOfWork unitOfWork; - @Inject - private PersistService persistService; - @Inject - private Provider<EntityManager> entityManager; - - @BeforeEach - public final void prepareGuice() { - Injector injector = Guice.createInjector( - new JpaPersistModule("testPersistenceUnit"), - new AbstractModule() { - @Override - protected void configure() { - final MutableFixedClock clock = new MutableFixedClock(Clock.systemDefaultZone()); - bind(Clock.class).toInstance(clock); - bind(MutableFixedClock.class).toInstance(clock); - } - }, - moduleUnderTest()); - - // Have to start the PersistService and UnitOfWork manually since they are no longer - // automatically started as an EntityManager is injected - injector.getInstance(PersistService.class).start(); - injector.getInstance(UnitOfWork.class).begin(); - - injector.injectMembers(this); - - persistService.start(); - EntityTransaction transaction = entityManager.get().getTransaction(); - transaction.begin(); - transaction.setRollbackOnly(); - } - - protected abstract Module moduleUnderTest(); - - @AfterEach - public final void shutDownPersistence() { - entityManager.get().getTransaction().rollback(); - unitOfWork.end(); - persistService.stop(); - } - - protected <T> T save(T entity) { - EntityManager em = entityManager.get(); - if (em.contains(entity)) { - return em.merge(entity); - } - else { - em.persist(entity); - return entity; - } - } -} diff --git a/core/src/test/java/se/su/dsv/scipro/test/IntegrationTest.java b/core/src/test/java/se/su/dsv/scipro/test/IntegrationTest.java index 4833f0e4bd..837f58dc90 100644 --- a/core/src/test/java/se/su/dsv/scipro/test/IntegrationTest.java +++ b/core/src/test/java/se/su/dsv/scipro/test/IntegrationTest.java @@ -1,57 +1,5 @@ package se.su.dsv.scipro.test; -import com.google.inject.AbstractModule; -import com.google.inject.Module; -import com.google.inject.name.Names; -import modules.CoreModule; -import se.su.dsv.scipro.file.FileModule; -import se.su.dsv.scipro.file.FileStore; -import se.su.dsv.scipro.grading.GradingHistory; -import se.su.dsv.scipro.grading.GradingHistoryEventRepository; -import se.su.dsv.scipro.grading.GradingHistoryEventRepositoryImpl; -import se.su.dsv.scipro.grading.GradingModule; -import se.su.dsv.scipro.grading.ThesisSubmissionHistoryService; -import se.su.dsv.scipro.plagiarism.urkund.UrkundModule; -import se.su.dsv.scipro.reviewing.ReviewingModule; -import se.su.dsv.scipro.sukat.SukatModule; -import se.su.dsv.scipro.system.CurrentUser; -import se.su.dsv.scipro.system.User; +public abstract class IntegrationTest extends SpringTest { -import jakarta.inject.Singleton; - -public abstract class IntegrationTest extends GuiceTest { - - @Override - protected Module moduleUnderTest() { - return new AbstractModule() { - @Override - protected void configure() { - bindConstant().annotatedWith(Names.named("profile")).to("TEST"); - install(new CoreModule()); - install(new FileModule()); - install(new ReviewingModule()); - install(new SukatModule()); - install(new UrkundModule()); - bind(ThesisSubmissionHistoryService.class).to(GradingHistory.class); - bind(GradingHistoryEventRepository.class).to(GradingHistoryEventRepositoryImpl.class); - bind(CurrentUser.class).to(TestUser.class); - bind(FileStore.class).to(InMemoryFileStore.class); - } - }; - } - - @Singleton - private static class TestUser implements CurrentUser { - - private User user; - - public void set(User user) { - this.user = user; - } - - @Override - public User get() { - return user; - } - } } diff --git a/core/src/test/java/se/su/dsv/scipro/test/SpringTest.java b/core/src/test/java/se/su/dsv/scipro/test/SpringTest.java new file mode 100644 index 0000000000..eae4492265 --- /dev/null +++ b/core/src/test/java/se/su/dsv/scipro/test/SpringTest.java @@ -0,0 +1,92 @@ +package se.su.dsv.scipro.test; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.EntityTransaction; +import jakarta.persistence.Persistence; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; + +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import se.su.dsv.scipro.profiles.CurrentProfile; +import se.su.dsv.scipro.sukat.Sukat; +import se.su.dsv.scipro.system.CurrentUser; +import se.su.dsv.scipro.CoreConfig; +import se.su.dsv.scipro.RepositoryConfiguration; + +import java.time.Clock; +import java.util.Optional; + +public abstract class SpringTest { + private EntityManager entityManager; + private EntityManagerFactory entityManagerFactory; + + @BeforeEach + public final void prepareSpring() { + entityManagerFactory = Persistence.createEntityManagerFactory("testPersistenceUnit"); + this.entityManager = entityManagerFactory.createEntityManager(); + EntityTransaction transaction = entityManager.getTransaction(); + transaction.begin(); + transaction.setRollbackOnly(); + + AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(); + annotationConfigApplicationContext.register(TestContext.class); + annotationConfigApplicationContext.getBeanFactory() + .registerSingleton("entityManager", this.entityManager); + annotationConfigApplicationContext.refresh(); + annotationConfigApplicationContext.getAutowireCapableBeanFactory() + .autowireBean(this); + } + + @AfterEach + public final void shutDownPersistence() { + entityManager.getTransaction().rollback(); + entityManager.close(); + entityManagerFactory.close(); + } + + protected <T> T save(T entity) { + EntityManager em = entityManager; + if (em.contains(entity)) { + return em.merge(entity); + } + else { + em.persist(entity); + return entity; + } + } + + @Configuration(proxyBeanMethods = false) + @Import({CoreConfig.class, RepositoryConfiguration.class}) + public static class TestContext { + @Bean + public InMemoryFileStore inMemoryFileStore() { + return new InMemoryFileStore(); + } + + @Bean + public MutableFixedClock clock() { + return new MutableFixedClock(Clock.systemDefaultZone()); + } + + @Bean + public Sukat sukat() { + return (username) -> Optional.empty(); + } + + @Bean + public CurrentUser currentUser() { + return () -> null; + } + + @Bean + public CurrentProfile currentProfile() { + CurrentProfile currentProfile = new CurrentProfile(); + currentProfile.setCurrentProfileString("DEV"); + return currentProfile; + } + } +} diff --git a/daisy-integration/pom.xml b/daisy-integration/pom.xml index 891a45a81e..3d94bb165c 100644 --- a/daisy-integration/pom.xml +++ b/daisy-integration/pom.xml @@ -17,8 +17,8 @@ <artifactId>core</artifactId> </dependency> <dependency> - <groupId>com.google.inject.extensions</groupId> - <artifactId>guice-servlet</artifactId> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> </dependency> <dependency> <groupId>jakarta.servlet</groupId> diff --git a/daisy-integration/src/main/java/se/su/dsv/scipro/daisyExternal/impl/ExternalImporterDaisyImpl.java b/daisy-integration/src/main/java/se/su/dsv/scipro/daisyExternal/impl/ExternalImporterDaisyImpl.java index 3d4acbe581..3f78ffd415 100755 --- a/daisy-integration/src/main/java/se/su/dsv/scipro/daisyExternal/impl/ExternalImporterDaisyImpl.java +++ b/daisy-integration/src/main/java/se/su/dsv/scipro/daisyExternal/impl/ExternalImporterDaisyImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.daisyExternal.impl; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import se.su.dsv.scipro.system.PageRequest; diff --git a/daisy-integration/src/main/java/se/su/dsv/scipro/daisyExternal/impl/ImporterTransactionsImpl.java b/daisy-integration/src/main/java/se/su/dsv/scipro/daisyExternal/impl/ImporterTransactionsImpl.java index 0fe1dd6e51..9e6ea05554 100644 --- a/daisy-integration/src/main/java/se/su/dsv/scipro/daisyExternal/impl/ImporterTransactionsImpl.java +++ b/daisy-integration/src/main/java/se/su/dsv/scipro/daisyExternal/impl/ImporterTransactionsImpl.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.daisyExternal.impl; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import jakarta.ws.rs.core.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/daisy-integration/src/main/java/se/su/dsv/scipro/integration/daisy/DaisyIntegrationConfiguration.java b/daisy-integration/src/main/java/se/su/dsv/scipro/integration/daisy/DaisyIntegrationConfiguration.java new file mode 100644 index 0000000000..1a50b0c056 --- /dev/null +++ b/daisy-integration/src/main/java/se/su/dsv/scipro/integration/daisy/DaisyIntegrationConfiguration.java @@ -0,0 +1,182 @@ +package se.su.dsv.scipro.integration.daisy; + +import com.google.common.eventbus.EventBus; +import jakarta.inject.Provider; +import jakarta.persistence.EntityManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import se.su.dsv.scipro.daisyExternal.ExternalImporter; +import se.su.dsv.scipro.daisyExternal.ImporterTransactions; +import se.su.dsv.scipro.daisyExternal.http.DaisyAPI; +import se.su.dsv.scipro.daisyExternal.impl.ExternalImporterDaisyImpl; +import se.su.dsv.scipro.daisyExternal.impl.ImporterTransactionsImpl; +import se.su.dsv.scipro.finalseminar.FinalSeminarService; +import se.su.dsv.scipro.finalthesis.FinalThesisService; +import se.su.dsv.scipro.forum.ProjectForumService; +import se.su.dsv.scipro.grading.NationalSubjectCategoryService; +import se.su.dsv.scipro.grading.ThesisApprovedHistoryService; +import se.su.dsv.scipro.grading.ThesisRejectionHistoryService; +import se.su.dsv.scipro.integration.daisy.workers.GradingCompletedMilestoneActivator; +import se.su.dsv.scipro.integration.daisy.workers.ImportNationalCategories; +import se.su.dsv.scipro.integration.daisy.workers.ProjectExporter; +import se.su.dsv.scipro.integration.daisy.workers.ProjectFinalizer; +import se.su.dsv.scipro.integration.daisy.workers.RejectedThesisWorker; +import se.su.dsv.scipro.integration.daisy.workers.UserImportWorker; +import se.su.dsv.scipro.io.ExternalExporter; +import se.su.dsv.scipro.io.facade.ExporterFacade; +import se.su.dsv.scipro.io.impl.ExternalExporterDaisyImpl; +import se.su.dsv.scipro.match.ProgramService; +import se.su.dsv.scipro.project.ProjectRepo; +import se.su.dsv.scipro.project.ProjectService; +import se.su.dsv.scipro.report.GradingReportService; +import se.su.dsv.scipro.springdata.services.UnitService; +import se.su.dsv.scipro.system.MergeService; +import se.su.dsv.scipro.system.MergeServiceImpl; +import se.su.dsv.scipro.system.ResearchAreaService; +import se.su.dsv.scipro.system.UserNameService; +import se.su.dsv.scipro.system.UserService; +import se.su.dsv.scipro.war.PluginConfiguration; +import se.su.dsv.scipro.workerthreads.Scheduler; + +@Configuration +public class DaisyIntegrationConfiguration implements PluginConfiguration { + @Bean + public Daisy daisy(ExporterFacade exporterFacade, ExternalExporter externalExporter) { + return new Daisy(exporterFacade, externalExporter); + } + + @Bean + public ExporterFacade exporterFacade(ExternalExporter externalExporter) { + return new ExporterFacade(externalExporter); + } + + @Bean + public ExternalExporterDaisyImpl externalExporter(DaisyAPI daisyApi) { + return new ExternalExporterDaisyImpl(daisyApi); + } + + @Bean + public DaisyWorkerInitialization daisyWorkerInitialization( + Scheduler scheduler, + Provider<ProjectExporter> projectExporter, + Provider<UserImportWorker> userImportWorker, + Provider<ProjectFinalizer> projectFinalizer, + Provider<RejectedThesisWorker> rejectedThesisWorkerProvider, + Provider<GradingCompletedMilestoneActivator> gradingFinalizer, + Provider<ImportNationalCategories> importNationalCategories) + { + return new DaisyWorkerInitialization(scheduler, projectExporter, userImportWorker, projectFinalizer, + rejectedThesisWorkerProvider, gradingFinalizer, importNationalCategories); + } + + @Bean + public ProjectExporter projectExporter( + ExporterFacade exporterFacade, + ProjectRepo projectRepo, + DaisyAPI daisyApi, + ExternalExporter externalExporter, + FinalSeminarService finalSeminarService, + FinalThesisService finalThesisService) + { + return new ProjectExporter(projectRepo, exporterFacade, daisyApi, externalExporter, finalSeminarService, + finalThesisService); + } + + @Bean + public UserImportWorker userImportWorker( + DaisyAPI daisyApi, + ImporterTransactions importerTransactions, + ExternalImporter externalImporter, + MergeService mergeService, + UserService userService, + ProgramService programService, + Provider<EntityManager> entityManager, + ResearchAreaService researchAreaService) + { + return new UserImportWorker(daisyApi, importerTransactions, externalImporter, mergeService, userService, + programService, entityManager, researchAreaService); + } + + @Bean + public ProjectFinalizer projectFinalizer( + ProjectService projectService, + DaisyAPI daisyApi, + ThesisApprovedHistoryService thesisApprovedHistoryService) + { + return new ProjectFinalizer(projectService, daisyApi, thesisApprovedHistoryService); + } + + @Bean + public RejectedThesisWorker rejectedThesisWorker( + GradingReportService gradingReportService, + ProjectService projectService, + FinalThesisService finalThesisService, + ProjectForumService projectForumService, + ThesisRejectionHistoryService thesisRejectionHistoryService, + DaisyAPI daisyApi) + { + return new RejectedThesisWorker(gradingReportService, projectService, finalThesisService, projectForumService, + thesisRejectionHistoryService, daisyApi); + } + + @Bean + public GradingCompletedMilestoneActivator gradingFinalizer( + ProjectService projectService, + DaisyAPI daisyApi, + EventBus eventBus, + UserService userService) + { + return new GradingCompletedMilestoneActivator(projectService, daisyApi, eventBus, userService); + } + + @Bean + public ImportNationalCategories importNationalCategories( + DaisyAPI daisyApi, + NationalSubjectCategoryService nationalSubjectCategoryService) + { + return new ImportNationalCategories(daisyApi, nationalSubjectCategoryService); + } + + @Bean + public ImporterTransactionsImpl importerTransactions( + UserService userService, + ResearchAreaService researchAreaService, + ProjectService projectService, + UserNameService userNameService, + DaisyAPI daisyApi, + ProgramService programService) + { + return new ImporterTransactionsImpl(userService, researchAreaService, projectService, userNameService, + daisyApi, programService); + } + + @Bean + public ExternalImporterDaisyImpl externalImporter( + DaisyAPI daisyApi, + ImporterTransactions importerTransactions, + UserService userService, + UnitService unitService) + { + return new ExternalImporterDaisyImpl(userService, unitService, daisyApi, importerTransactions); + } + + @Bean + public MergeServiceImpl mergeService(UserService userService, UserNameService userNameService) { + return new MergeServiceImpl(userNameService, userService); + } + + @Bean + SyncReviewerWithDaisy syncReviewerWithDaisy(DaisyAPI daisyApi, EventBus eventBus) { + return new SyncReviewerWithDaisy(daisyApi, eventBus); + } + + @Bean + public DaisyUserSearchService daisyUserSearchService(DaisyAPI daisyApi, UserService userService) { + return new DaisyUserSearchService(daisyApi, userService); + } + + @Bean + DaisyConsentService daisyConsentService(DaisyAPI daisyApi) { + return new DaisyConsentService(daisyApi); + } +} diff --git a/daisy-integration/src/main/java/se/su/dsv/scipro/integration/daisy/DaisyModule.java b/daisy-integration/src/main/java/se/su/dsv/scipro/integration/daisy/DaisyModule.java deleted file mode 100644 index ffedb6c3c1..0000000000 --- a/daisy-integration/src/main/java/se/su/dsv/scipro/integration/daisy/DaisyModule.java +++ /dev/null @@ -1,44 +0,0 @@ -package se.su.dsv.scipro.integration.daisy; - -import com.google.inject.multibindings.Multibinder; -import com.google.inject.multibindings.OptionalBinder; -import com.google.inject.servlet.ServletModule; -import se.su.dsv.scipro.daisyExternal.ExternalImporter; -import se.su.dsv.scipro.daisyExternal.ImporterTransactions; -import se.su.dsv.scipro.daisyExternal.impl.ExternalImporterDaisyImpl; -import se.su.dsv.scipro.daisyExternal.impl.ImporterTransactionsImpl; -import se.su.dsv.scipro.finalthesis.PublishingConsentService; -import se.su.dsv.scipro.integration.daisy.workers.ProjectExporter; -import se.su.dsv.scipro.integration.daisy.workers.UserImportWorker; -import se.su.dsv.scipro.io.ExternalExporter; -import se.su.dsv.scipro.io.impl.ExternalExporterDaisyImpl; -import se.su.dsv.scipro.match.IdeaCreationJudge; -import se.su.dsv.scipro.system.UserImportService; -import se.su.dsv.scipro.system.UserSearchProvider; - -public class DaisyModule extends ServletModule { - @Override - protected void configureServlets() { - bind(ExternalImporter.class).to(ExternalImporterDaisyImpl.class); - bind(ImporterTransactions.class).to(ImporterTransactionsImpl.class); - - OptionalBinder.newOptionalBinder(binder(), IdeaCreationJudge.class) - .setBinding().to(Daisy.class); - - bind(ExternalExporter.class).to(ExternalExporterDaisyImpl.class); - bind(UserImportWorker.class); - bind(ProjectExporter.class); - bind(DaisyWorkerInitialization.class).asEagerSingleton(); - bind(SyncReviewerWithDaisy.class).asEagerSingleton(); - - Multibinder.newSetBinder(binder(), UserImportService.class) - .addBinding().to(ExternalImporterDaisyImpl.class); - - Multibinder.newSetBinder(binder(), UserSearchProvider.class) - .addBinding().to(DaisyUserSearchService.class); - - OptionalBinder.newOptionalBinder(binder(), PublishingConsentService.class) - .setBinding().to(DaisyConsentService.class); - } - -} diff --git a/daisy-integration/src/main/java/se/su/dsv/scipro/io/facade/ExporterFacade.java b/daisy-integration/src/main/java/se/su/dsv/scipro/io/facade/ExporterFacade.java index 4d7c11803d..75400ab642 100755 --- a/daisy-integration/src/main/java/se/su/dsv/scipro/io/facade/ExporterFacade.java +++ b/daisy-integration/src/main/java/se/su/dsv/scipro/io/facade/ExporterFacade.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.io.facade; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.io.ExternalExporter; import se.su.dsv.scipro.io.dto.Role; import se.su.dsv.scipro.io.exceptions.ExternalExportException; diff --git a/daisy-integration/src/main/resources/META-INF/services/com.google.inject.Module b/daisy-integration/src/main/resources/META-INF/services/com.google.inject.Module deleted file mode 100644 index f216e38b02..0000000000 --- a/daisy-integration/src/main/resources/META-INF/services/com.google.inject.Module +++ /dev/null @@ -1 +0,0 @@ -se.su.dsv.scipro.integration.daisy.DaisyModule diff --git a/daisy-integration/src/main/resources/META-INF/services/se.su.dsv.scipro.war.PluginConfiguration b/daisy-integration/src/main/resources/META-INF/services/se.su.dsv.scipro.war.PluginConfiguration new file mode 100644 index 0000000000..39148f50a9 --- /dev/null +++ b/daisy-integration/src/main/resources/META-INF/services/se.su.dsv.scipro.war.PluginConfiguration @@ -0,0 +1 @@ +se.su.dsv.scipro.integration.daisy.DaisyIntegrationConfiguration diff --git a/daisy-integration/src/test/java/se/su/dsv/scipro/integration/daisy/workers/GradingCompletedMilestoneActivatorTest.java b/daisy-integration/src/test/java/se/su/dsv/scipro/integration/daisy/workers/GradingCompletedMilestoneActivatorTest.java index b583b29e21..f51c23592a 100644 --- a/daisy-integration/src/test/java/se/su/dsv/scipro/integration/daisy/workers/GradingCompletedMilestoneActivatorTest.java +++ b/daisy-integration/src/test/java/se/su/dsv/scipro/integration/daisy/workers/GradingCompletedMilestoneActivatorTest.java @@ -1,10 +1,6 @@ package se.su.dsv.scipro.integration.daisy.workers; import com.google.common.eventbus.EventBus; -import com.google.inject.persist.UnitOfWork; -import com.google.inject.util.Providers; -import jakarta.persistence.EntityManager; -import jakarta.persistence.EntityTransaction; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -23,6 +19,7 @@ import se.su.dsv.scipro.system.User; import se.su.dsv.scipro.system.UserService; import se.su.dsv.scipro.workerthreads.WorkerData; import se.su.dsv.scipro.workerthreads.WorkerDataService; +import se.su.dsv.scipro.workerthreads.WorkerTransactionManager; import java.util.*; @@ -47,22 +44,16 @@ public class GradingCompletedMilestoneActivatorTest { @Mock private EventBus eventBus; @Mock - private UnitOfWork unitOfWork; - @Mock - private EntityManager entityManager; - @Mock - private EntityTransaction entityTransaction; + private WorkerTransactionManager workerTransactionManager; @Mock private WorkerDataService workerDataService; @BeforeEach public void setup() { gradingCompletedMilestoneActivator = new GradingCompletedMilestoneActivator(projectService, daisyAPI, eventBus, userService); - gradingCompletedMilestoneActivator.setUnitOfWork(unitOfWork); - gradingCompletedMilestoneActivator.setTxManager(Providers.of(entityManager)); + gradingCompletedMilestoneActivator.setTxManager(workerTransactionManager); gradingCompletedMilestoneActivator.setWorkerDataService(workerDataService); when(workerDataService.save(any(WorkerData.class))).thenReturn(new WorkerData()); - when(entityManager.getTransaction()).thenReturn(entityTransaction); project.setId(3493L); project.setIdentifier(234); diff --git a/daisy-integration/src/test/java/se/su/dsv/scipro/integration/daisy/workers/ProjectExporterTest.java b/daisy-integration/src/test/java/se/su/dsv/scipro/integration/daisy/workers/ProjectExporterTest.java index f4165842bb..dfd523ad4f 100644 --- a/daisy-integration/src/test/java/se/su/dsv/scipro/integration/daisy/workers/ProjectExporterTest.java +++ b/daisy-integration/src/test/java/se/su/dsv/scipro/integration/daisy/workers/ProjectExporterTest.java @@ -1,10 +1,6 @@ package se.su.dsv.scipro.integration.daisy.workers; -import com.google.inject.persist.UnitOfWork; -import com.google.inject.util.Providers; import com.querydsl.core.types.Predicate; -import jakarta.persistence.EntityManager; -import jakarta.persistence.EntityTransaction; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -26,6 +22,7 @@ import se.su.dsv.scipro.system.Unit; import se.su.dsv.scipro.system.User; import se.su.dsv.scipro.workerthreads.WorkerData; import se.su.dsv.scipro.workerthreads.WorkerDataService; +import se.su.dsv.scipro.workerthreads.WorkerTransactionManager; import java.time.LocalDate; import java.util.*; @@ -45,10 +42,8 @@ public class ProjectExporterTest { private @Mock ExporterFacade exporterFacade; private @Mock DaisyAPI daisyAPI; private @Mock ExternalExporter externalExporter; - private @Mock EntityManager entityManager; - private @Mock EntityTransaction entityTransaction; + private @Mock WorkerTransactionManager workerTransactionManager; private @Mock WorkerDataService workerDataService; - private @Mock UnitOfWork unitOfWork; private @Mock FinalSeminarService finalSeminarService; private @Mock FinalThesisService finalThesisService; @@ -61,11 +56,9 @@ public class ProjectExporterTest { @BeforeEach public void setUp() { projectExporter = new ProjectExporter(projectRepo, exporterFacade, daisyAPI, externalExporter, finalSeminarService, finalThesisService); - projectExporter.setTxManager(Providers.of(entityManager)); + projectExporter.setTxManager(workerTransactionManager); projectExporter.setWorkerDataService(workerDataService); - projectExporter.setUnitOfWork(unitOfWork); when(workerDataService.save(any(WorkerData.class))).thenReturn(new WorkerData()); - when(entityManager.getTransaction()).thenReturn(entityTransaction); Unit unit = new Unit(); unit.setIdentifier(239478); diff --git a/daisy-integration/src/test/java/se/su/dsv/scipro/integration/daisy/workers/ProjectFinalizerTest.java b/daisy-integration/src/test/java/se/su/dsv/scipro/integration/daisy/workers/ProjectFinalizerTest.java index 576409136a..048d2165e7 100644 --- a/daisy-integration/src/test/java/se/su/dsv/scipro/integration/daisy/workers/ProjectFinalizerTest.java +++ b/daisy-integration/src/test/java/se/su/dsv/scipro/integration/daisy/workers/ProjectFinalizerTest.java @@ -1,7 +1,5 @@ package se.su.dsv.scipro.integration.daisy.workers; -import com.google.inject.persist.UnitOfWork; -import com.google.inject.util.Providers; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -18,8 +16,8 @@ import se.su.dsv.scipro.project.QProject; import se.su.dsv.scipro.workerthreads.WorkerData; import se.su.dsv.scipro.workerthreads.WorkerDataService; -import jakarta.persistence.EntityManager; -import jakarta.persistence.EntityTransaction; +import se.su.dsv.scipro.workerthreads.WorkerTransactionManager; + import java.util.Collections; import java.util.List; import java.util.Optional; @@ -38,9 +36,7 @@ public class ProjectFinalizerTest { private @Mock DaisyAPI daisyAPI; private @Mock ProjectService projectService; - private @Mock UnitOfWork unitOfWork; - private @Mock EntityManager entityManager; - private @Mock EntityTransaction entityTransaction; + private @Mock WorkerTransactionManager workerTransactionManager; private @Mock WorkerDataService workerDataService; private @Mock ThesisApprovedHistoryService thesisApprovedHistoryService; @@ -48,11 +44,9 @@ public class ProjectFinalizerTest { @BeforeEach public void setup() { projectFinalizer = new ProjectFinalizer(projectService, daisyAPI, thesisApprovedHistoryService); - projectFinalizer.setUnitOfWork(unitOfWork); - projectFinalizer.setTxManager(Providers.of(entityManager)); + projectFinalizer.setTxManager(workerTransactionManager); projectFinalizer.setWorkerDataService(workerDataService); when(workerDataService.save(any(WorkerData.class))).thenReturn(new WorkerData()); - when(entityManager.getTransaction()).thenReturn(entityTransaction); project.setId(3493L); project.setIdentifier(234); diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000..637455a39e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +services: + oauth2: + container_name: scipro-dev-oauth2 + build: + context: https://github.com/dsv-su/toker.git + dockerfile: embedded.Dockerfile + restart: on-failure + ports: + - '59733:8080' + environment: + - CLIENT_ID=get-token + - CLIENT_SECRET=get-token-secret + - CLIENT_REDIRECT_URI=http://localhost:59732/ + - RESOURCE_SERVER_ID=scipro-api-client + - RESOURCE_SERVER_SECRET=scipro-api-secret diff --git a/pom.xml b/pom.xml index d222069a72..c96cb4a122 100755 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,8 @@ <module>core</module> <module>view</module> <module>daisy-integration</module> + <module>war</module> + <module>api</module> </modules> <properties> @@ -36,7 +38,6 @@ <mockito.version>5.3.1</mockito.version> <flyway.version>9.19.1</flyway.version> <jersey.version>3.1.6</jersey.version> - <guice.version>7.0.0</guice.version> <poi.version>5.2.5</poi.version> <jackson.version>2.17.0</jackson.version> @@ -88,9 +89,22 @@ </dependency> <dependency> <groupId>org.apache.wicket</groupId> - <artifactId>wicket-guice</artifactId> + <artifactId>wicket-ioc</artifactId> <version>${wicket.version}</version> </dependency> + <dependency> + <groupId>org.apache.wicket</groupId> + <artifactId>wicket-spring</artifactId> + <version>${wicket.version}</version> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-dependencies</artifactId> + <version>3.2.5</version> + <scope>import</scope> + <type>pom</type> + </dependency> <!-- Servlet API, needed for compilation. --> <dependency> @@ -189,13 +203,6 @@ <artifactId>guava</artifactId> <version>32.0.1-jre</version> </dependency> - <dependency> - <groupId>com.google.inject</groupId> - <artifactId>guice-bom</artifactId> - <version>${guice.version}</version> - <type>pom</type> - <scope>import</scope> - </dependency> <dependency> <groupId>jakarta.mail</groupId> @@ -260,6 +267,11 @@ <artifactId>flyway-mysql</artifactId> <version>${flyway.version}</version> </dependency> + <dependency> + <groupId>org.springdoc</groupId> + <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> + <version>2.5.0</version> + </dependency> </dependencies> </dependencyManagement> diff --git a/view/pom.xml b/view/pom.xml index c359d76206..9cdd26f28b 100644 --- a/view/pom.xml +++ b/view/pom.xml @@ -13,15 +13,6 @@ <packaging>war</packaging> <dependencies> - <dependency> - <groupId>com.google.inject.extensions</groupId> - <artifactId>guice-servlet</artifactId> - </dependency> - <dependency> - <groupId>com.google.inject.extensions</groupId> - <artifactId>guice-persist</artifactId> - </dependency> - <dependency> <groupId>se.su.dsv.scipro</groupId> <artifactId>core</artifactId> @@ -44,7 +35,7 @@ </dependency> <dependency> <groupId>org.apache.wicket</groupId> - <artifactId>wicket-guice</artifactId> + <artifactId>wicket-ioc</artifactId> </dependency> <dependency> <groupId>org.apache.wicket</groupId> @@ -55,6 +46,11 @@ <artifactId>wicket-tester</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.apache.wicket</groupId> + <artifactId>wicket-spring</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.wicketstuff</groupId> <artifactId>wicketstuff-jasperreports</artifactId> @@ -144,6 +140,15 @@ </dependencies> <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-war-plugin</artifactId> + <configuration> + <attachClasses>true</attachClasses> + </configuration> + </plugin> + </plugins> <resources> <resource> <filtering>true</filtering> diff --git a/view/src/main/java/ApplicationBootstrap.java b/view/src/main/java/ApplicationBootstrap.java deleted file mode 100644 index d5631e6f1c..0000000000 --- a/view/src/main/java/ApplicationBootstrap.java +++ /dev/null @@ -1,68 +0,0 @@ -import com.google.inject.AbstractModule; -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.google.inject.Module; -import com.google.inject.name.Names; -import com.google.inject.persist.PersistFilter; -import com.google.inject.servlet.GuiceServletContextListener; -import com.google.inject.servlet.ServletModule; -import org.apache.wicket.guice.GuiceWebApplicationFactory; -import org.apache.wicket.protocol.http.WicketFilter; - -import jakarta.servlet.ServletContext; -import java.net.CookieHandler; -import java.net.CookieManager; -import java.time.Clock; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; -import java.util.ServiceLoader; - -public class ApplicationBootstrap extends GuiceServletContextListener { - @Override - protected Injector getInjector() { - // preserve cookies when using Jersey which will use the logged in session cookie from - // Daisy API thus drastically speeding up the batch jobs - CookieHandler.setDefault(new CookieManager()); - return Guice.createInjector( - new ServletModule() { - @Override - protected void configureServlets() { - final ServletContext servletContext = getServletContext(); - final Enumeration<String> initParameterNames = servletContext.getInitParameterNames(); - while (initParameterNames.hasMoreElements()) { - final String parameterName = initParameterNames.nextElement(); - final String value = servletContext.getInitParameter(parameterName); - bindConstant().annotatedWith(Names.named(parameterName)).to(value); - } - } - }, - new ServletModule() { - @Override - protected void configureServlets() { - filter("/*").through(PersistFilter.class); - } - }, - new AbstractModule() { - @Override - protected void configure() { - bind(Clock.class).toInstance(Clock.systemDefaultZone()); - ServiceLoader<Module> modules = ServiceLoader.load(Module.class); - for (Module module : modules) { - install(module); - } - } - }, - new ServletModule() { - @Override - protected void configureServlets() { - Map<String,String> params = new HashMap<>(); - params.put(WicketFilter.FILTER_MAPPING_PARAM, "/*"); - params.put(WicketFilter.APP_FACT_PARAM, GuiceWebApplicationFactory.class.getName()); - params.put("injectorContextAttribute", Injector.class.getName()); - filter("/*").through(new WicketFilter(), params); - } - } - ); - } -} diff --git a/view/src/main/java/DatabaseMigration.java b/view/src/main/java/DatabaseMigration.java deleted file mode 100644 index 442e3003e4..0000000000 --- a/view/src/main/java/DatabaseMigration.java +++ /dev/null @@ -1,35 +0,0 @@ -import org.flywaydb.core.Flyway; - -import javax.naming.InitialContext; -import javax.naming.NamingException; -import jakarta.servlet.ServletContextEvent; -import jakarta.servlet.ServletContextListener; -import javax.sql.DataSource; - -public class DatabaseMigration implements ServletContextListener { - @Override - public void contextInitialized(ServletContextEvent sce) { - migrateDatabase(); - } - - private void migrateDatabase() { - Flyway flyway = Flyway.configure() - .dataSource(getDataSource()) - .baselineOnMigrate(true) - .table("schema_version") - .load(); - flyway.migrate(); - } - - private DataSource getDataSource() { - try { - return InitialContext.doLookup("java:comp/env/jdbc/sciproDS"); - } catch (NamingException e) { - throw new RuntimeException(e); - } - } - - @Override - public void contextDestroyed(ServletContextEvent sce) { - } -} diff --git a/view/src/main/java/se/su/dsv/scipro/FileSystemStore.java b/view/src/main/java/se/su/dsv/scipro/FileSystemStore.java index 7e80019776..3d0eafc255 100644 --- a/view/src/main/java/se/su/dsv/scipro/FileSystemStore.java +++ b/view/src/main/java/se/su/dsv/scipro/FileSystemStore.java @@ -12,7 +12,7 @@ import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.nio.file.StandardOpenOption; -class FileSystemStore implements FileStore { +public class FileSystemStore implements FileStore { private static final int FILES_PER_SUBDIRECTORY = 1000; private static final String FILE_ROOT = "/scipro-files"; diff --git a/view/src/main/java/se/su/dsv/scipro/SciProApplication.java b/view/src/main/java/se/su/dsv/scipro/SciProApplication.java index ebbc21afa8..521595f7c3 100755 --- a/view/src/main/java/se/su/dsv/scipro/SciProApplication.java +++ b/view/src/main/java/se/su/dsv/scipro/SciProApplication.java @@ -53,7 +53,6 @@ import se.su.dsv.scipro.milestones.pages.SupervisorMileStonePage; import se.su.dsv.scipro.nonworkdays.NonWorkDaysPage; import se.su.dsv.scipro.notes.NotesPage; import se.su.dsv.scipro.notifications.NotificationLoader; -import se.su.dsv.scipro.notifications.NotificationModule; import se.su.dsv.scipro.notifications.pages.NotificationLandingPage; import se.su.dsv.scipro.notifications.pages.NotificationsPage; import se.su.dsv.scipro.notifications.pages.SupervisorNotificationSettingsPage; @@ -347,7 +346,7 @@ public class SciProApplication extends LifecycleManagedWebApplication { private void mountNotificationAndSettingsPages() { mountPage("notes", NotesPage.class); - mountPage(NotificationModule.NOTIFICATION_RELATIVE_PAGE_URL, NotificationLandingPage.class); + mountPage("notification", NotificationLandingPage.class); mountPage("notifications", NotificationsPage.class); mountPage("settings", BasicProfilePage.class); mountPage("settings/supervisorprofile", SupervisorProfilePage.class); diff --git a/view/src/main/java/se/su/dsv/scipro/SciProModule.java b/view/src/main/java/se/su/dsv/scipro/SciProModule.java deleted file mode 100644 index 26e7f0a6ba..0000000000 --- a/view/src/main/java/se/su/dsv/scipro/SciProModule.java +++ /dev/null @@ -1,33 +0,0 @@ -package se.su.dsv.scipro; - -import com.google.inject.Singleton; -import com.google.inject.multibindings.Multibinder; -import com.google.inject.persist.jpa.JpaPersistModule; -import com.google.inject.servlet.ServletModule; -import com.google.inject.servlet.SessionScoped; -import modules.CoreModule; -import org.apache.wicket.protocol.http.WebApplication; -import se.su.dsv.scipro.file.FileModule; -import se.su.dsv.scipro.file.FileStore; -import se.su.dsv.scipro.security.auth.AuthenticationModule; -import se.su.dsv.scipro.system.CurrentUser; -import se.su.dsv.scipro.system.Lifecycle; -import se.su.dsv.scipro.workerthreads.WorkerModule; - -public class SciProModule extends ServletModule { - @Override - protected void configureServlets() { - install(new JpaPersistModule("defaultPersistenceUnit")); - install(new CoreModule()); - install(new FileModule()); - bind(FileStore.class).to(FileSystemStore.class); - install(new WorkerModule()); - install(new AuthenticationModule()); - - bind(WebApplication.class).to(SciProApplication.class).in(Singleton.class); - - bind(CurrentUser.class).to(CurrentUserFromWicketSession.class).in(SessionScoped.class); - Multibinder<Lifecycle> lifecycles = Multibinder.newSetBinder(binder(), Lifecycle.class); - lifecycles.addBinding().to(DataInitializer.class); - } -} diff --git a/view/src/main/java/se/su/dsv/scipro/admin/pages/AdminCreateProjectConfirmationPage.java b/view/src/main/java/se/su/dsv/scipro/admin/pages/AdminCreateProjectConfirmationPage.java index 5b1e8d22fe..0b3b45f8ae 100644 --- a/view/src/main/java/se/su/dsv/scipro/admin/pages/AdminCreateProjectConfirmationPage.java +++ b/view/src/main/java/se/su/dsv/scipro/admin/pages/AdminCreateProjectConfirmationPage.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.admin.pages; -import com.google.inject.Inject; +import jakarta.inject.Inject; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.link.Link; diff --git a/view/src/main/java/se/su/dsv/scipro/admin/panels/AdminEditFooterAddressPanel.java b/view/src/main/java/se/su/dsv/scipro/admin/panels/AdminEditFooterAddressPanel.java index 48e268a040..eb36d66e9e 100644 --- a/view/src/main/java/se/su/dsv/scipro/admin/panels/AdminEditFooterAddressPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/admin/panels/AdminEditFooterAddressPanel.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.admin.panels; -import com.google.inject.persist.Transactional; +import jakarta.transaction.Transactional; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.RequiredTextField; import org.apache.wicket.markup.html.panel.Panel; diff --git a/view/src/main/java/se/su/dsv/scipro/crosscutting/CrosscuttingModule.java b/view/src/main/java/se/su/dsv/scipro/crosscutting/CrosscuttingModule.java deleted file mode 100644 index fc50e7ff37..0000000000 --- a/view/src/main/java/se/su/dsv/scipro/crosscutting/CrosscuttingModule.java +++ /dev/null @@ -1,17 +0,0 @@ -package se.su.dsv.scipro.crosscutting; - -import com.google.common.eventbus.EventBus; -import com.google.inject.AbstractModule; -import se.su.dsv.scipro.reviewing.ReviewerAssignedDeadline; - -public class CrosscuttingModule extends AbstractModule { - @Override - protected void configure() { - requireBinding(EventBus.class); - bind(ReviewingNotifications.class).asEagerSingleton(); - bind(ReviewerSupportMailer.class).asEagerSingleton(); - bind(ReviewerAssignedNotifications.class).asEagerSingleton(); - bind(ReviewerAssignedDeadline.class).asEagerSingleton(); - bind(ForwardPhase2Feedback.class).asEagerSingleton(); - } -} diff --git a/view/src/main/java/se/su/dsv/scipro/match/SupervisorIdeaDetailsPage.java b/view/src/main/java/se/su/dsv/scipro/match/SupervisorIdeaDetailsPage.java index da362486f4..51f921ae60 100644 --- a/view/src/main/java/se/su/dsv/scipro/match/SupervisorIdeaDetailsPage.java +++ b/view/src/main/java/se/su/dsv/scipro/match/SupervisorIdeaDetailsPage.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.match; -import com.google.inject.Inject; +import jakarta.inject.Inject; import org.apache.wicket.request.mapper.parameter.PageParameters; import org.apache.wicket.util.string.StringValue; import se.su.dsv.scipro.components.menuhighlighting.MenuHighlightSupervisorMyIdeas; diff --git a/view/src/main/java/se/su/dsv/scipro/peer/PeerReviewFilterDetailsPanel.java b/view/src/main/java/se/su/dsv/scipro/peer/PeerReviewFilterDetailsPanel.java index 5cca6a2310..144dd24f30 100644 --- a/view/src/main/java/se/su/dsv/scipro/peer/PeerReviewFilterDetailsPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/peer/PeerReviewFilterDetailsPanel.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.peer; -import com.google.inject.Inject; +import jakarta.inject.Inject; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.Model; diff --git a/view/src/main/java/se/su/dsv/scipro/peer/PeerReviewStatusStatisticsPanel.java b/view/src/main/java/se/su/dsv/scipro/peer/PeerReviewStatusStatisticsPanel.java index 18381874c6..2193555a56 100644 --- a/view/src/main/java/se/su/dsv/scipro/peer/PeerReviewStatusStatisticsPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/peer/PeerReviewStatusStatisticsPanel.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.peer; -import com.google.inject.Inject; +import jakarta.inject.Inject; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator; import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder; diff --git a/view/src/main/java/se/su/dsv/scipro/supervisor/panels/SupervisorApprovalPanel.java b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/SupervisorApprovalPanel.java index 3a39a1088c..32920d25d7 100644 --- a/view/src/main/java/se/su/dsv/scipro/supervisor/panels/SupervisorApprovalPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/SupervisorApprovalPanel.java @@ -1,6 +1,6 @@ package se.su.dsv.scipro.supervisor.panels; -import com.google.inject.Inject; +import jakarta.inject.Inject; import org.apache.wicket.feedback.FencedFeedbackPanel; import org.apache.wicket.markup.head.IHeaderResponse; import org.apache.wicket.markup.head.OnEventHeaderItem; diff --git a/view/src/main/resources/META-INF/services/com.google.inject.Module b/view/src/main/resources/META-INF/services/com.google.inject.Module deleted file mode 100644 index c0c493be41..0000000000 --- a/view/src/main/resources/META-INF/services/com.google.inject.Module +++ /dev/null @@ -1,15 +0,0 @@ -se.su.dsv.scipro.SciProModule -se.su.dsv.scipro.reviewing.ReviewingModule -se.su.dsv.scipro.crosscutting.CrosscuttingModule -se.su.dsv.scipro.integration.activityfinalseminar.ActivityFinalSeminarModule -se.su.dsv.scipro.integration.activityforum.ActivityForumModule -se.su.dsv.scipro.peer.PeerModule -se.su.dsv.scipro.firstmeeting.FirstMeetingModule -se.su.dsv.scipro.forum.notifications.ForumNotificationsModule -se.su.dsv.scipro.daisyExternal.DaisyExternalModule -se.su.dsv.scipro.plagiarism.urkund.UrkundModule -se.su.dsv.scipro.sukat.SukatModule -se.su.dsv.scipro.oauth.OAuthModule -se.su.dsv.scipro.grading.GradingModule -se.su.dsv.scipro.gdpr.GDPRModule -se.su.dsv.scipro.survey.SurveyModule diff --git a/view/src/main/webapp/WEB-INF/web.xml b/view/src/main/webapp/WEB-INF/web.xml deleted file mode 100755 index bf2a938984..0000000000 --- a/view/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" - version="4.0" metadata-complete="true"> - - <display-name>SciPro</display-name> - - <filter> - <filter-name>guiceFilter</filter-name> - <filter-class>com.google.inject.servlet.GuiceFilter</filter-class> - </filter> - <filter-mapping> - <filter-name>guiceFilter</filter-name> - <url-pattern>/*</url-pattern> - </filter-mapping> - - <listener> - <listener-class>ApplicationBootstrap</listener-class> - </listener> - - <listener> - <listener-class>DatabaseMigration</listener-class> - </listener> - - <session-config> - <session-timeout>480</session-timeout> - </session-config> -</web-app> diff --git a/view/src/test/java/se/su/dsv/scipro/SciProTest.java b/view/src/test/java/se/su/dsv/scipro/SciProTest.java index ee39fc8b41..e712c36790 100755 --- a/view/src/test/java/se/su/dsv/scipro/SciProTest.java +++ b/view/src/test/java/se/su/dsv/scipro/SciProTest.java @@ -1,17 +1,13 @@ package se.su.dsv.scipro; import com.google.common.eventbus.EventBus; -import com.google.inject.AbstractModule; -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.google.inject.multibindings.Multibinder; -import com.google.inject.name.Names; import org.apache.wicket.Component; import org.apache.wicket.Page; import org.apache.wicket.Session; -import org.apache.wicket.guice.GuiceComponentInjector; import org.apache.wicket.request.Request; import org.apache.wicket.request.Response; +import org.apache.wicket.spring.injection.annot.SpringComponentInjector; +import org.apache.wicket.spring.test.ApplicationContextMock; import org.apache.wicket.util.tester.WicketTester; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; @@ -364,9 +360,12 @@ public abstract class SciProTest { @BeforeEach public void setUpApplication() { final Class<? extends SciProTest> clazz = getClass(); - final Injector injector = Guice.createInjector(new MockModule(clazz)); + ApplicationContextMock applicationContext = new MockModule(clazz); - SciProApplication application = new SciProApplication(injector.getInstance(CurrentProfile.class)) { + CurrentProfile currentProfile = new CurrentProfile(); + currentProfile.setCurrentProfileString("TEST"); + + SciProApplication application = new SciProApplication(currentProfile) { @Override public Session newSession(Request request, Response response) { @@ -374,7 +373,7 @@ public abstract class SciProTest { } }; application.getComponentInstantiationListeners().add( - new GuiceComponentInjector(application, injector)); + new SpringComponentInjector(application, applicationContext)); tester = new WicketTester(application, System.getProperty("user.dir") + "/src/main/webapp"); setLoggedIn(true); @@ -467,27 +466,23 @@ public abstract class SciProTest { return sb.toString(); } - private class MockModule extends AbstractModule { + private class MockModule extends ApplicationContextMock { private final Class<? extends SciProTest> clazz; public MockModule(Class<? extends SciProTest> clazz) { this.clazz = clazz; + configure(); } @SuppressWarnings("unchecked") - @Override - protected void configure() { - Multibinder.newSetBinder(binder(), Lifecycle.class); - Multibinder.newSetBinder(binder(), UserImportService.class) - .addBinding().toInstance(userImportService); - bindConstant().annotatedWith(Names.named("profile")).to("TEST"); - bind(Clock.class).toInstance(Clock.systemDefaultZone()); + private void configure() { + putBean(Clock.systemDefaultZone()); for (Class<?> c = clazz; c != null; c = c.getSuperclass()) { for (Field f : c.getDeclaredFields()) { if (f.getAnnotation(Mock.class) != null && f.trySetAccessible()) { try { Class<Object> type = (Class<Object>) f.getType(); - bind(type).toInstance(f.get(SciProTest.this)); + putBean(f.getName(), f.get(SciProTest.this)); } catch (IllegalAccessException e) { throw new RuntimeException(e); } diff --git a/war/pom.xml b/war/pom.xml new file mode 100644 index 0000000000..2c4ad17242 --- /dev/null +++ b/war/pom.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>se.su.dsv.scipro</groupId> + <artifactId>SciPro</artifactId> + <version>0.1-SNAPSHOT</version> + </parent> + + <artifactId>war</artifactId> + <packaging>war</packaging> + + <dependencies> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + <exclusions> + <!-- exclude default logging implementation (logback) since we want log4j2 --> + <exclusion> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-logging</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-log4j2</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-security</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-oauth2-resource-server</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-tomcat</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-orm</artifactId> + </dependency> + <dependency> + <groupId>org.hibernate.orm</groupId> + <artifactId>hibernate-core</artifactId> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>org.apache.wicket</groupId> + <artifactId>wicket-spring</artifactId> + </dependency> + + <dependency> + <groupId>org.springdoc</groupId> + <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> + </dependency> + + <dependency> + <groupId>se.su.dsv.scipro</groupId> + <artifactId>view</artifactId> + <version>${project.version}</version> + <type>war</type> + </dependency> + <dependency> + <!-- needed only at compile time --> + <!-- the classes will be moved as part of the overlay by the war plugin --> + <groupId>se.su.dsv.scipro</groupId> + <artifactId>view</artifactId> + <version>${project.version}</version> + <classifier>classes</classifier> + <optional>true</optional> + </dependency> + <dependency> + <groupId>se.su.dsv.scipro</groupId> + <artifactId>api</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-war-plugin</artifactId> + <version>3.4.0</version> + <configuration> + <overlays> + <overlay> + <groupId>se.su.dsv.scipro</groupId> + <artifactId>view</artifactId> + <type>war</type> + </overlay> + </overlays> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/war/src/main/java/se/su/dsv/scipro/war/ApiConfig.java b/war/src/main/java/se/su/dsv/scipro/war/ApiConfig.java new file mode 100644 index 0000000000..f8b410b8aa --- /dev/null +++ b/war/src/main/java/se/su/dsv/scipro/war/ApiConfig.java @@ -0,0 +1,72 @@ +package se.su.dsv.scipro.war; + +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; +import org.springframework.web.servlet.handler.HandlerMappingIntrospector; + +import java.util.List; + +@Configuration(proxyBeanMethods = false) +@ComponentScan("se.su.dsv.scipro.api") +public class ApiConfig { + @Bean + @Order(1) + public SecurityFilterChain documentationSecurity( + HttpSecurity http, + HandlerMappingIntrospector introspector, + WebMvcProperties webMvcProperties) + throws Exception + { + MvcRequestMatcher.Builder mvc = new MvcRequestMatcher.Builder(introspector) + .servletPath(webMvcProperties.getServlet().getPath()); + return http + .securityMatchers(matchers -> matchers + .requestMatchers( + mvc.pattern("/v3/api-docs/**"), + mvc.pattern("/swagger"), + mvc.pattern("/swagger-ui/**"))) + .authorizeHttpRequests(authorize -> authorize.anyRequest().permitAll()) + .build(); + } + + @Bean + @Order(2) + public SecurityFilterChain apiSecurity( + HttpSecurity http, + HandlerMappingIntrospector introspector, + WebMvcProperties webMvcProperties) + throws Exception + { + MvcRequestMatcher.Builder mvc = new MvcRequestMatcher.Builder(introspector) + .servletPath(webMvcProperties.getServlet().getPath()); + return http + .securityMatcher(mvc.pattern("/**")) + .authorizeHttpRequests(authorize -> authorize + .anyRequest().authenticated()) + .oauth2ResourceServer(oauth2 -> oauth2.opaqueToken(Customizer.withDefaults())) + .build(); + } + + @Bean + public OpenAPI customOpenAPI() { + return new OpenAPI() + .security(List.of(new SecurityRequirement().addList("access-token"))) + .components(new Components() + .addSecuritySchemes("access-token", new SecurityScheme() + .type(SecurityScheme.Type.HTTP) + .in(SecurityScheme.In.HEADER) + .scheme("bearer") + .bearerFormat("opaque"))); + } +} diff --git a/core/src/main/java/se/su/dsv/scipro/mail/MailModule.java b/war/src/main/java/se/su/dsv/scipro/war/MailConfig.java similarity index 52% rename from core/src/main/java/se/su/dsv/scipro/mail/MailModule.java rename to war/src/main/java/se/su/dsv/scipro/war/MailConfig.java index c23bc66811..a96c89f56c 100644 --- a/core/src/main/java/se/su/dsv/scipro/mail/MailModule.java +++ b/war/src/main/java/se/su/dsv/scipro/war/MailConfig.java @@ -1,38 +1,40 @@ -package se.su.dsv.scipro.mail; - -import com.google.inject.Exposed; -import com.google.inject.PrivateModule; -import com.google.inject.Provides; -import se.su.dsv.scipro.file.FileService; -import se.su.dsv.scipro.generalsystemsettings.GeneralSystemSettingsService; -import se.su.dsv.scipro.profiles.CurrentProfile; +package se.su.dsv.scipro.war; import jakarta.mail.Session; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import se.su.dsv.scipro.data.facade.MailFacade; +import se.su.dsv.scipro.file.FileService; +import se.su.dsv.scipro.generalsystemsettings.GeneralSystemSettingsService; +import se.su.dsv.scipro.mail.Mail; +import se.su.dsv.scipro.mail.Mailer; +import se.su.dsv.scipro.mail.PrintingMailer; +import se.su.dsv.scipro.mail.RedirectingMailer; +import se.su.dsv.scipro.profiles.CurrentProfile; + import java.util.Properties; -public class MailModule extends PrivateModule { - - private static final String TEST_MAIL_SINK = "scipro-mailtest@dsv.su.se"; - - @Override - protected void configure() { - requireBinding(CurrentProfile.class); - requireBinding(GeneralSystemSettingsService.class); - bind(MailEventService.class).to(MailEventServiceImpl.class); - expose(MailEventService.class); +@Configuration(proxyBeanMethods = false) +public class MailConfig { + @Bean + public MailFacade mailFacade() { + return new MailFacade(); } - @Provides - @Exposed - public Mailer mailer(CurrentProfile currentProfile, Session session, FileService fileDescriptionService) { + @Bean + public Mailer mailer( + CurrentProfile currentProfile, + Session session, + FileService fileDescriptionService) + { return switch (currentProfile.getCurrentProfile()) { case DEV -> new PrintingMailer(); case PROD -> new Mail(session, fileDescriptionService); - case TEST -> new RedirectingMailer(session, TEST_MAIL_SINK, fileDescriptionService); + case TEST -> new RedirectingMailer(session, "scipro-mailtest@dsv.su.se", fileDescriptionService); }; } - @Provides + @Bean public Session session(GeneralSystemSettingsService generalSystemSettings) { String smtpHost = generalSystemSettings.getGeneralSystemSettingsInstance().getSmtpServer(); Properties properties = new Properties(); diff --git a/war/src/main/java/se/su/dsv/scipro/war/Main.java b/war/src/main/java/se/su/dsv/scipro/war/Main.java new file mode 100644 index 0000000000..026130dd7d --- /dev/null +++ b/war/src/main/java/se/su/dsv/scipro/war/Main.java @@ -0,0 +1,168 @@ +package se.su.dsv.scipro.war; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.servlet.ServletContainerInitializer; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.autoconfigure.orm.jpa.EntityManagerFactoryBuilderCustomizer; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.core.task.SimpleAsyncTaskExecutor; +import org.springframework.orm.jpa.SharedEntityManagerCreator; +import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter; +import se.su.dsv.scipro.CoreConfig; +import se.su.dsv.scipro.CurrentUserFromWicketSession; +import se.su.dsv.scipro.FileSystemStore; +import se.su.dsv.scipro.RepositoryConfiguration; +import se.su.dsv.scipro.file.FileStore; +import se.su.dsv.scipro.finalthesis.PublishingConsentService; +import se.su.dsv.scipro.finalthesis.PublishingConsentUnavailable; +import se.su.dsv.scipro.profiles.CurrentProfile; +import se.su.dsv.scipro.system.AggregateUserSearch; +import se.su.dsv.scipro.system.Lifecycle; +import se.su.dsv.scipro.system.ResearchArea; +import se.su.dsv.scipro.system.User; +import se.su.dsv.scipro.system.UserImportService; +import se.su.dsv.scipro.system.UserSearchProvider; +import se.su.dsv.scipro.system.UserSearchService; +import se.su.dsv.scipro.system.UserService; + +import java.time.Clock; +import java.util.List; +import java.util.Optional; +import java.util.ServiceLoader; +import java.util.Set; + +@SpringBootApplication(proxyBeanMethods = false) +@EntityScan("se.su.dsv.scipro") +@Import({ + CoreConfig.class, + ApiConfig.class, + WorkerConfig.class, + MailConfig.class, + RepositoryConfiguration.class, + WicketConfiguration.class +}) +public class Main extends SpringBootServletInitializer implements ServletContainerInitializer { + @Override + public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException { + onStartup(ctx); + } + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { + for (PluginConfiguration pluginConfiguration : ServiceLoader.load(PluginConfiguration.class)) { + builder.sources(pluginConfiguration.getClass()); + } + return builder.sources(Main.class); + } + + @Bean + public EntityManagerFactoryBuilderCustomizer entityManagerFactoryCustomizer() { + return factoryBuilder -> { + factoryBuilder.setBootstrapExecutor(new SimpleAsyncTaskExecutor()); + }; + } + + @Bean + public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() { + return new OpenEntityManagerInViewFilter(); + } + + @Bean + public CurrentProfile currentProfile(@Value("${profile}" ) String profile) { + CurrentProfile currentProfile = new CurrentProfile(); + currentProfile.setCurrentProfileString(profile); + return currentProfile; + } + + @Bean + public CurrentUserFromWicketSession currentUserFromWicketSession() { + return new CurrentUserFromWicketSession(); + } + + @Bean + public FileStore fileStore() { + return new FileSystemStore(); + } + + @Bean + public Clock clock() { + return Clock.systemDefaultZone(); + } + + /** + * Allow injecting of {@link EntityManager} directly instead of {@link EntityManagerFactory} + */ + @Bean + public EntityManager entityManager(EntityManagerFactory emf) { + return SharedEntityManagerCreator.createSharedEntityManager(emf); + } + + /** + * Exists because Spring refuses to inject a collection of beans if there are no beans of that type. + */ + @Bean + public UserImportService dummyUserImportService() { + return new UserImportService() { + @Override + public Optional<User> importUser(String userName) { + return Optional.empty(); + } + + @Override + public List<ImportableUser> search(String searchTerm) { + return List.of(); + } + + @Override + public void importUser(ImportableUser importableUser) { + // do nothing + } + + @Override + public Set<ResearchArea> importResearchAreasForSupervisor(User supervisor) { + return Set.of(); + } + }; + } + + /** + * Exists because Spring refuses to inject a collection of beans if there are no beans of that type. + */ + @Bean + public Lifecycle dummyLifecycle() { + return new Lifecycle() { + @Override + public void start() { + // do nothing + } + + @Override + public void stop() { + // do nothing + } + }; + } + + @Bean + public UserSearchService aggregateSearchService( + Set<UserSearchProvider> userSearchProviders, + UserService userService) + { + return new AggregateUserSearch(userSearchProviders, userService); + } + + @Bean + @ConditionalOnMissingBean(PublishingConsentService.class) + public PublishingConsentUnavailable publishingConsentService() { + return new PublishingConsentUnavailable(); + } +} diff --git a/war/src/main/java/se/su/dsv/scipro/war/SpringManagedWorkerTransactions.java b/war/src/main/java/se/su/dsv/scipro/war/SpringManagedWorkerTransactions.java new file mode 100644 index 0000000000..ae66a50e36 --- /dev/null +++ b/war/src/main/java/se/su/dsv/scipro/war/SpringManagedWorkerTransactions.java @@ -0,0 +1,50 @@ +package se.su.dsv.scipro.war; + +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.TransactionStatus; +import se.su.dsv.scipro.workerthreads.WorkerTransactionManager; + +public class SpringManagedWorkerTransactions implements WorkerTransactionManager { + private final PlatformTransactionManager platformTransactionManager; + + private TransactionStatus activeTransaction; + + public SpringManagedWorkerTransactions(PlatformTransactionManager platformTransactionManager) { + this.platformTransactionManager = platformTransactionManager; + } + + @Override + public void rollbackIfActive() { + if (this.activeTransaction != null) { + platformTransactionManager.rollback(this.activeTransaction); + this.activeTransaction = null; + } + } + + @Override + public void begin() { + if (this.activeTransaction != null) { + throw new IllegalStateException("A transaction is already active"); + } + this.activeTransaction = platformTransactionManager.getTransaction(TransactionDefinition.withDefaults()); + } + + @Override + public void commit() { + if (this.activeTransaction == null) { + throw new IllegalStateException("A transaction is not active"); + } + platformTransactionManager.commit(this.activeTransaction); + this.activeTransaction = null; + } + + @Override + public void rollback() { + if (this.activeTransaction == null) { + throw new IllegalStateException("A transaction is not active"); + } + platformTransactionManager.rollback(this.activeTransaction); + this.activeTransaction = null; + } +} diff --git a/war/src/main/java/se/su/dsv/scipro/war/WicketConfiguration.java b/war/src/main/java/se/su/dsv/scipro/war/WicketConfiguration.java new file mode 100644 index 0000000000..f31d390c16 --- /dev/null +++ b/war/src/main/java/se/su/dsv/scipro/war/WicketConfiguration.java @@ -0,0 +1,90 @@ +package se.su.dsv.scipro.war; + +import com.google.common.eventbus.EventBus; +import org.apache.wicket.protocol.http.WebApplication; +import org.apache.wicket.protocol.http.WicketFilter; +import org.apache.wicket.spring.injection.annot.SpringComponentInjector; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import se.su.dsv.scipro.SciProApplication; +import se.su.dsv.scipro.crosscutting.ForwardPhase2Feedback; +import se.su.dsv.scipro.crosscutting.ReviewerAssignedNotifications; +import se.su.dsv.scipro.crosscutting.ReviewerSupportMailer; +import se.su.dsv.scipro.crosscutting.ReviewingNotifications; +import se.su.dsv.scipro.forum.ProjectForumService; +import se.su.dsv.scipro.generalsystemsettings.GeneralSystemSettingsService; +import se.su.dsv.scipro.mail.MailEventService; +import se.su.dsv.scipro.notifications.NotificationController; +import se.su.dsv.scipro.profiles.CurrentProfile; +import se.su.dsv.scipro.reviewing.FinalSeminarApprovalService; +import se.su.dsv.scipro.reviewing.RoughDraftApprovalService; + +@Configuration +public class WicketConfiguration { + @Bean + public FilterRegistrationBean<WicketFilter> wicket( + WebApplication webApplication, + ApplicationContext applicationContext) + { + webApplication.getComponentInstantiationListeners() + .add(new SpringComponentInjector(webApplication, applicationContext)); + + WicketFilter filter = new WicketFilter(webApplication); + filter.setFilterPath(""); + + FilterRegistrationBean<WicketFilter> registration = new FilterRegistrationBean<>(); + registration.setFilter(filter); + registration.addUrlPatterns("/*"); + registration.setMatchAfter(true); + return registration; + } + + @Bean + public WebApplication webApplication(CurrentProfile currentProfile) { + return new SciProApplication(currentProfile); + } + + @Bean + public ReviewingNotifications reviewingNotifications( + EventBus eventBus, + NotificationController notificationController, + GeneralSystemSettingsService generalSystemSettingsService, + WebApplication webApplication) + { + return new ReviewingNotifications(eventBus, notificationController, generalSystemSettingsService, + webApplication); + } + + @Bean + public ForwardPhase2Feedback forwardPhase2Feedback( + EventBus eventBus, + WebApplication webApplication, + ProjectForumService projectForumService) + { + return new ForwardPhase2Feedback(webApplication, projectForumService, eventBus); + } + + // Not sure why this dependency lives in the view module + @Bean + public ReviewerSupportMailer reviewerSupportMailer( + EventBus eventBus, + GeneralSystemSettingsService generalSystemSettingsService, + MailEventService mailEventService) + { + return new ReviewerSupportMailer(eventBus, mailEventService, generalSystemSettingsService); + } + + // Not sure why this dependency lives in the view module + @Bean + public ReviewerAssignedNotifications reviewerAssignedNotifications( + EventBus eventBus, + NotificationController notificationController, + RoughDraftApprovalService roughDraftApprovalService, + FinalSeminarApprovalService finalSeminarApprovalService) + { + return new ReviewerAssignedNotifications(roughDraftApprovalService, + finalSeminarApprovalService, notificationController, eventBus); + } +} diff --git a/war/src/main/java/se/su/dsv/scipro/war/WorkerConfig.java b/war/src/main/java/se/su/dsv/scipro/war/WorkerConfig.java new file mode 100644 index 0000000000..076bc219fc --- /dev/null +++ b/war/src/main/java/se/su/dsv/scipro/war/WorkerConfig.java @@ -0,0 +1,245 @@ +package se.su.dsv.scipro.war; + +import com.google.common.eventbus.EventBus; +import jakarta.inject.Provider; +import jakarta.persistence.EntityManagerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.Scope; +import org.springframework.transaction.PlatformTransactionManager; +import se.su.dsv.scipro.file.FileService; +import se.su.dsv.scipro.finalseminar.FinalSeminarService; +import se.su.dsv.scipro.firstmeeting.FirstMeetingReminderWorker; +import se.su.dsv.scipro.firstmeeting.FirstMeetingService; +import se.su.dsv.scipro.generalsystemsettings.GeneralSystemSettingsService; +import se.su.dsv.scipro.mail.MailEventService; +import se.su.dsv.scipro.mail.MailEventWorker; +import se.su.dsv.scipro.mail.Mailer; +import se.su.dsv.scipro.match.AllowAllIdeaCreationJudge; +import se.su.dsv.scipro.match.ApplicationPeriodService; +import se.su.dsv.scipro.match.IdeaCreationJudge; +import se.su.dsv.scipro.match.IdeaService; +import se.su.dsv.scipro.misc.DaysService; +import se.su.dsv.scipro.peer.ExpiredRequestWorker; +import se.su.dsv.scipro.peer.ExpiredReviewResetWorker; +import se.su.dsv.scipro.peer.PeerWorkerSchedules; +import se.su.dsv.scipro.plagiarism.PlagiarismRequestRepository; +import se.su.dsv.scipro.plagiarism.PlagiarismSubmitter; +import se.su.dsv.scipro.plagiarism.urkund.StatusPollingWorker; +import se.su.dsv.scipro.plagiarism.urkund.UrkundApi; +import se.su.dsv.scipro.plagiarism.urkund.UrkundService; +import se.su.dsv.scipro.plagiarism.urkund.UrkundSettings; +import se.su.dsv.scipro.plagiarism.urkund.UrkundSettingsRepository; +import se.su.dsv.scipro.plagiarism.urkund.UrkundSubmissionRepository; +import se.su.dsv.scipro.project.ProjectService; +import se.su.dsv.scipro.projectpartner.ProjectPartnerRepository; +import se.su.dsv.scipro.projectpartner.RemoveFulfilledPartnerAdsWorker; +import se.su.dsv.scipro.reviewing.MyReviewService; +import se.su.dsv.scipro.reviewing.ReviewerDecisionReminderWorker; +import se.su.dsv.scipro.sukat.Sukat; +import se.su.dsv.scipro.workerthreads.GradeFinalSeminarParticipantReminderWorker; +import se.su.dsv.scipro.workerthreads.IdeaExportWorker; +import se.su.dsv.scipro.workerthreads.ManualMatchRemindWorker; +import se.su.dsv.scipro.workerthreads.NotificationCompilationWorker; +import se.su.dsv.scipro.workerthreads.Scheduler; +import se.su.dsv.scipro.workerthreads.SchedulerImpl; +import se.su.dsv.scipro.workerthreads.TemporaryWorkerScheduler; +import se.su.dsv.scipro.workerthreads.ThesisUploadDeadlineWorker; +import se.su.dsv.scipro.workerthreads.ThesisUploadReminderWorker; +import se.su.dsv.scipro.workerthreads.WorkerTransactionManager; + +import java.time.Clock; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; + +@Configuration(proxyBeanMethods = false) +@Import(WorkerConfig.Workers.class) +public class WorkerConfig { + private static final int NUMBER_OF_WORKER_THREADS = 4; + + @Bean + public ScheduledExecutorService scheduledExecutorService() { + return Executors.newScheduledThreadPool(NUMBER_OF_WORKER_THREADS); + } + + @Bean + public SchedulerImpl scheduler( + ScheduledExecutorService scheduledExecutorService, + EntityManagerFactory entityManagerFactory) + { + return new SchedulerImpl(scheduledExecutorService, entityManagerFactory); + } + + @Bean + public TemporaryWorkerScheduler temporaryWorkerScheduler( + Scheduler scheduler, + Provider<MailEventWorker> mailEventWorker, + Provider<NotificationCompilationWorker> notificationCompilationWorker, + Provider<IdeaExportWorker> ideaExportWorker, + Provider<ThesisUploadReminderWorker> thesisUploadReminderWorker, + Provider<ThesisUploadDeadlineWorker> thesisUploadDeadlineWorker, + Provider<ManualMatchRemindWorker> manualMatchRemindWorkerProvider, + Provider<ReviewerDecisionReminderWorker> reviewerDecisionReminderWorker, + Provider<PlagiarismSubmitter> plagiarismSubmitter, + Provider<StatusPollingWorker> urkundPoller, + Provider<RemoveFulfilledPartnerAdsWorker> removeFulfilledPartnerAds, + Provider<GradeFinalSeminarParticipantReminderWorker> gradeFinalSeminarParticipantReminderWorkerProvider) + { + return new TemporaryWorkerScheduler(scheduler, mailEventWorker, notificationCompilationWorker, ideaExportWorker, thesisUploadReminderWorker, thesisUploadDeadlineWorker, manualMatchRemindWorkerProvider, reviewerDecisionReminderWorker, plagiarismSubmitter, urkundPoller, removeFulfilledPartnerAds, gradeFinalSeminarParticipantReminderWorkerProvider); + } + + @Bean + public FirstMeetingReminderWorker.FirstMeetingReminderWorkerSchedule firstMeetingReminderWorkerScheduler( + Scheduler scheduler, + Provider<FirstMeetingReminderWorker> firstMeetingReminderWorkerProvider) + { + return new FirstMeetingReminderWorker.FirstMeetingReminderWorkerSchedule(scheduler, firstMeetingReminderWorkerProvider); + } + + @Bean + public PeerWorkerSchedules peerWorkerSchedules( + Scheduler scheduler, + Provider<ExpiredRequestWorker> expiredRequestWorker, + Provider<ExpiredReviewResetWorker> expiredReviewResetWorker) + { + return new PeerWorkerSchedules(scheduler, expiredRequestWorker, expiredReviewResetWorker); + } + + @Bean + @ConditionalOnMissingBean(IdeaCreationJudge.class) + public IdeaCreationJudge ideaCreationJudge() { + return new AllowAllIdeaCreationJudge(); + } + + @Bean + public PlagiarismSubmitter plagiarismSubmitter( + Provider<UrkundSettings> urkundSettings, + PlagiarismRequestRepository plagiarismRequestRepository, + UrkundService urkundService, + FileService fileService) + { + return new PlagiarismSubmitter(urkundSettings, plagiarismRequestRepository, urkundService, fileService); + } + + @Bean + public UrkundSettings urkundSettings(UrkundSettingsRepository urkundSettingsRepository) { + return urkundSettingsRepository.getSettings(); + } + + @Bean + @Scope("prototype") + public WorkerTransactionManager workerTransactionManager(PlatformTransactionManager platformTransactionManager) { + return new SpringManagedWorkerTransactions(platformTransactionManager); + } + + @Configuration + public static class Workers { + @Bean + public MailEventWorker mailEventWorker( + MailEventService mailEventService, + GeneralSystemSettingsService generalSystemSettingsService, + Mailer mailer) + { + return new MailEventWorker(mailEventService, generalSystemSettingsService, mailer); + } + + @Bean + public NotificationCompilationWorker notificationCompilationWorker() { + return new NotificationCompilationWorker(); + } + + @Bean + public IdeaExportWorker ideaExportWorker( + IdeaService ideaService, + MailEventService mailEventService, + ProjectService projectService, + IdeaCreationJudge ideaCreationJudge, + EventBus eventBus, + FirstMeetingService firstMeetingService) + { + return new IdeaExportWorker(ideaService, mailEventService, projectService, ideaCreationJudge, eventBus, + firstMeetingService); + } + + @Bean + public ThesisUploadReminderWorker thesisUploadReminderWorker() { + return new ThesisUploadReminderWorker(); + } + + @Bean + public ThesisUploadDeadlineWorker thesisUploadDeadlineWorker() { + return new ThesisUploadDeadlineWorker(); + } + + @Bean + public ManualMatchRemindWorker manualMatchRemindWorker( + ApplicationPeriodService applicationPeriodService, + MailEventService mailEventService, + GeneralSystemSettingsService generalSystemSettingsService, + IdeaService ideaService, + Clock clock) + { + return new ManualMatchRemindWorker(applicationPeriodService, mailEventService, generalSystemSettingsService, + ideaService, clock); + } + + @Bean + public ReviewerDecisionReminderWorker reviewerDecisionReminderWorker( + MyReviewService myReviewService, + DaysService daysService, + MailEventService mailEventService) + { + return new ReviewerDecisionReminderWorker(myReviewService, daysService, mailEventService); + } + + @Bean + public StatusPollingWorker statusPollingWorker( + UrkundSubmissionRepository urkundSubmissionRepository, + UrkundApi urkundApi, + Provider<UrkundSettings> urkundSettingsProvider, + Sukat sukat) + { + return new StatusPollingWorker(urkundSubmissionRepository, urkundApi, urkundSettingsProvider, sukat); + } + + @Bean + public RemoveFulfilledPartnerAdsWorker removeFulfilledPartnerAdsWorker( + IdeaService ideaService, + ProjectPartnerRepository projectPartnerRepository) + { + return new RemoveFulfilledPartnerAdsWorker(ideaService, projectPartnerRepository); + } + + @Bean + public GradeFinalSeminarParticipantReminderWorker gradeFinalSeminarParticipantReminderWorker( + MailEventService mailEventService, + GeneralSystemSettingsService generalSystemSettingsService, + FinalSeminarService finalSeminarService) + { + return new GradeFinalSeminarParticipantReminderWorker(finalSeminarService, mailEventService, generalSystemSettingsService); + } + + @Bean + public FirstMeetingReminderWorker firstMeetingReminderWorker( + IdeaService ideaService, + DaysService daysService, + MailEventService mailEventService, + GeneralSystemSettingsService generalSystemSettingsService, + Clock clock) + { + return new FirstMeetingReminderWorker(ideaService, daysService, mailEventService, generalSystemSettingsService, clock); + } + + @Bean + public ExpiredReviewResetWorker expiredReviewResetWorker() { + return new ExpiredReviewResetWorker(); + } + + @Bean + public ExpiredRequestWorker expiredRequestWorker() { + return new ExpiredRequestWorker(); + } + } +} diff --git a/core/src/main/java/se/su/dsv/scipro/workerthreads/SchedulerImpl.java b/war/src/main/java/se/su/dsv/scipro/workerthreads/SchedulerImpl.java similarity index 63% rename from core/src/main/java/se/su/dsv/scipro/workerthreads/SchedulerImpl.java rename to war/src/main/java/se/su/dsv/scipro/workerthreads/SchedulerImpl.java index d8ecf35252..0acb56920c 100755 --- a/core/src/main/java/se/su/dsv/scipro/workerthreads/SchedulerImpl.java +++ b/war/src/main/java/se/su/dsv/scipro/workerthreads/SchedulerImpl.java @@ -1,12 +1,18 @@ package se.su.dsv.scipro.workerthreads; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.orm.jpa.EntityManagerFactoryUtils; +import org.springframework.orm.jpa.EntityManagerHolder; +import org.springframework.transaction.support.TransactionSynchronizationManager; import se.su.dsv.scipro.system.Lifecycle; import jakarta.inject.Inject; import jakarta.inject.Provider; import jakarta.inject.Singleton; + import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -19,13 +25,15 @@ public class SchedulerImpl implements Lifecycle, Scheduler { private static final Logger LOGGER = LoggerFactory.getLogger(SchedulerImpl.class); private final ScheduledExecutorService scheduledExecutorService; + private final EntityManagerFactory emf; private final Set<Task> tasks = new TreeSet<>(new Task.ByDescriptionComparator()); private final Set<Task> runningWorkers = Collections.synchronizedSet(new HashSet<>()); @Inject - public SchedulerImpl(ScheduledExecutorService scheduledExecutorService) { + public SchedulerImpl(ScheduledExecutorService scheduledExecutorService, EntityManagerFactory emf) { this.scheduledExecutorService = scheduledExecutorService; + this.emf = emf; } @Override @@ -43,6 +51,14 @@ public class SchedulerImpl implements Lifecycle, Scheduler { private Runnable tracked(final Task task) { return () -> { try { + // Since we're not in a web request when running a scheduled job, Spring's OpenEntityManagerInView + // filter is not active. Therefore, we need to manually bind a new EntityManager to the current thread + // to be shared by all DAOs. If we do not, we will get problems with detached entity passed to persist + // since every read and write from the database will be in a new EntityManager. + EntityManager em = emf.createEntityManager(); + EntityManagerHolder emHolder = new EntityManagerHolder(em); + TransactionSynchronizationManager.bindResource(emf, emHolder); + runningWorkers.add(task); task.execute(); } @@ -51,6 +67,11 @@ public class SchedulerImpl implements Lifecycle, Scheduler { } finally { runningWorkers.remove(task); + + // Clean up the shared EntityManager + EntityManagerHolder emHolder = (EntityManagerHolder) + TransactionSynchronizationManager.unbindResource(emf); + EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager()); } }; } diff --git a/core/src/main/java/se/su/dsv/scipro/workerthreads/TaskScheduling.java b/war/src/main/java/se/su/dsv/scipro/workerthreads/TaskScheduling.java similarity index 100% rename from core/src/main/java/se/su/dsv/scipro/workerthreads/TaskScheduling.java rename to war/src/main/java/se/su/dsv/scipro/workerthreads/TaskScheduling.java diff --git a/war/src/main/resources/META-INF/services/jakarta.servlet.ServletContainerInitializer b/war/src/main/resources/META-INF/services/jakarta.servlet.ServletContainerInitializer new file mode 100644 index 0000000000..ad4ffa3bbd --- /dev/null +++ b/war/src/main/resources/META-INF/services/jakarta.servlet.ServletContainerInitializer @@ -0,0 +1 @@ +se.su.dsv.scipro.war.Main diff --git a/war/src/main/resources/application.properties b/war/src/main/resources/application.properties new file mode 100644 index 0000000000..753d0e323c --- /dev/null +++ b/war/src/main/resources/application.properties @@ -0,0 +1,20 @@ +spring.datasource.jndi-name=java:/comp/env/jdbc/sciproDS +spring.flyway.table=schema_version + +# Spring Boot changes Hibernates default naming strategy to convert camelCase to snake_case +# We currently rely on the names to be treated as they are in Java, so we need to set it back to the default +spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl + +# We also need to set the implicit strategy to be JPA compliant, as we rely on this naming strategy for certain +# join tables (idea_Keyword vs idea_keyword) +spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl + +spring.mvc.servlet.path=/api + +springdoc.swagger-ui.path=/swagger +springdoc.swagger-ui.persist-authorization=true + +# These will be overwritten by configuration in the environment of servers it is deployed to +spring.security.oauth2.resourceserver.opaquetoken.client-id=scipro-api-client +spring.security.oauth2.resourceserver.opaquetoken.client-secret=scipro-api-secret +spring.security.oauth2.resourceserver.opaquetoken.introspection-uri=http://localhost:59733/introspect diff --git a/war/src/main/webapp/WEB-INF/web.xml b/war/src/main/webapp/WEB-INF/web.xml new file mode 100755 index 0000000000..b346f3b49c --- /dev/null +++ b/war/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" + version="4.0" metadata-complete="true"> + + <display-name>SciPro</display-name> + + <!-- disables Spring's built in ServletContainerInitializer which causes a slow class path scanning --> + <absolute-ordering/> + + <session-config> + <session-timeout>480</session-timeout> + </session-config> +</web-app> diff --git a/core/src/test/java/se/su/dsv/scipro/workerthreads/SchedulerImplTest.java b/war/src/test/java/se/su/dsv/scipro/workerthreads/SchedulerImplTest.java similarity index 83% rename from core/src/test/java/se/su/dsv/scipro/workerthreads/SchedulerImplTest.java rename to war/src/test/java/se/su/dsv/scipro/workerthreads/SchedulerImplTest.java index 45e9ec4f67..f79a05cd26 100644 --- a/core/src/test/java/se/su/dsv/scipro/workerthreads/SchedulerImplTest.java +++ b/war/src/test/java/se/su/dsv/scipro/workerthreads/SchedulerImplTest.java @@ -1,8 +1,10 @@ package se.su.dsv.scipro.workerthreads; -import com.google.inject.util.Providers; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Answers; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; @@ -24,6 +26,8 @@ public class SchedulerImplTest { private Worker abstractWorker; @Mock private Task task; + @Mock(answer = Answers.RETURNS_MOCKS) + private EntityManagerFactory emf; @InjectMocks private SchedulerImpl scheduler; @@ -31,7 +35,7 @@ public class SchedulerImplTest { public void schedules_correctly() { long period = 1; TimeUnit timeUnit = TimeUnit.SECONDS; - scheduler.schedule("My worker").runBy(Providers.of(abstractWorker)).every(period, timeUnit); + scheduler.schedule("My worker").runBy(() -> abstractWorker).every(period, timeUnit); verify(scheduledExecutorService).scheduleAtFixedRate(any(Runnable.class), eq(period), eq(period), eq(timeUnit)); } From 8e5c9f5687488f1fe89581c3a65389120148e74c Mon Sep 17 00:00:00 2001 From: Andreas Svanberg <andreass@dsv.su.se> Date: Mon, 11 Nov 2024 11:17:15 +0100 Subject: [PATCH 2/8] Allow longer final thesis titles (#17) The titles entered are most often the same as the project title. The project title however has no length limit. When such a project tries to upload their final thesis the system will crash because the accepted long project title is rejected as the final thesis title. This change removes the length limit on final thesis titles to bring them to parity with the project title. See OTRS ticket [202411011026](https://otrs.dsv.su.se/otrs/index.pl?Action=AgentTicketZoom;TicketID=389771#1413199) This change has already been done manually in the production system to resolve the above ticket. ## How to test Submit a final thesis using a title longer than 255 characters and see that is accepted. Reviewed-on: https://gitea.dsv.su.se/DMC/scipro/pulls/17 Reviewed-by: niat8586 <nico@dsv.su.se> Co-authored-by: Andreas Svanberg <andreass@dsv.su.se> Co-committed-by: Andreas Svanberg <andreass@dsv.su.se> --- .../db/migration/V390__longer_titles_in_final_thesis.sql | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 core/src/main/resources/db/migration/V390__longer_titles_in_final_thesis.sql diff --git a/core/src/main/resources/db/migration/V390__longer_titles_in_final_thesis.sql b/core/src/main/resources/db/migration/V390__longer_titles_in_final_thesis.sql new file mode 100644 index 0000000000..3edeeb923b --- /dev/null +++ b/core/src/main/resources/db/migration/V390__longer_titles_in_final_thesis.sql @@ -0,0 +1,3 @@ +-- Match what project.title allows +ALTER TABLE `FinalThesis` MODIFY `englishTitle` LONGTEXT NULL; +ALTER TABLE `FinalThesis` MODIFY `swedishTitle` LONGTEXT NULL; From cfe61a9ed8cc3b55a32d8aa1e20e22f136f08f2f Mon Sep 17 00:00:00 2001 From: Tom Zhao <tom.zhao@dsv.su.se> Date: Tue, 12 Nov 2024 13:33:43 +0100 Subject: [PATCH 3/8] task/3382: Harmonize database names as snake_case (#6) Co-authored-by: Andreas Svanberg <andreass@dsv.su.se> Reviewed-on: https://gitea.dsv.su.se/DMC/scipro/pulls/6 Reviewed-by: ansv7779 <andreass@dsv.su.se> Co-authored-by: Tom Zhao <tom.zhao@dsv.su.se> Co-committed-by: Tom Zhao <tom.zhao@dsv.su.se> --- .../su/dsv/scipro/activityplan/Activity.java | 196 +- .../dsv/scipro/activityplan/ActivityPlan.java | 104 +- .../activityplan/ActivityPlanTemplate.java | 166 +- .../scipro/activityplan/ActivityTemplate.java | 136 +- .../se/su/dsv/scipro/checklist/Checklist.java | 39 +- .../dsv/scipro/checklist/ChecklistAnswer.java | 93 +- .../scipro/checklist/ChecklistAnswerEnum.java | 2 +- .../scipro/checklist/ChecklistCategory.java | 18 +- .../scipro/checklist/ChecklistQuestion.java | 29 +- .../scipro/checklist/ChecklistTemplate.java | 41 +- .../su/dsv/scipro/file/FileDescription.java | 204 +- .../se/su/dsv/scipro/file/FileReference.java | 4 +- .../se/su/dsv/scipro/file/ProjectFile.java | 89 +- .../dsv/scipro/finalseminar/FinalSeminar.java | 462 +-- .../FinalSeminarActiveParticipation.java | 28 +- .../finalseminar/FinalSeminarOpposition.java | 112 +- .../FinalSeminarParticipation.java | 107 +- .../finalseminar/FinalSeminarRespondent.java | 8 +- .../finalseminar/FinalSeminarSettings.java | 14 +- .../dsv/scipro/finalthesis/FinalThesis.java | 315 +- .../firstmeeting/ProjectFirstMeeting.java | 54 +- .../scipro/forum/dataobjects/ForumPost.java | 106 +- .../forum/dataobjects/ForumPostReadState.java | 18 +- .../dataobjects/ForumPostReadStateId.java | 4 +- .../scipro/forum/dataobjects/ForumThread.java | 144 +- .../scipro/forum/dataobjects/GroupThread.java | 59 +- .../forum/dataobjects/ProjectThread.java | 66 +- .../forum/dataobjects/ReviewerThread.java | 65 +- .../notifications/ForumNotification.java | 46 +- .../GeneralSystemSettings.java | 51 +- .../su/dsv/scipro/grading/ApprovedEvent.java | 47 +- .../grading/NationalSubjectCategory.java | 40 +- .../scipro/grading/PublicationMetadata.java | 65 +- .../su/dsv/scipro/grading/RejectionEvent.java | 59 +- .../dsv/scipro/grading/SubmissionEvent.java | 71 +- .../java/se/su/dsv/scipro/group/Group.java | 182 +- .../ActivityFinalSeminar.java | 42 +- .../activityforum/ActivityThread.java | 46 +- .../java/se/su/dsv/scipro/mail/MailEvent.java | 261 +- .../dsv/scipro/match/ApplicationPeriod.java | 36 +- .../match/ApplicationPeriodExemption.java | 21 +- .../match/ApplicationPeriodProjectType.java | 6 + .../se/su/dsv/scipro/match/FirstMeeting.java | 104 +- .../java/se/su/dsv/scipro/match/Idea.java | 200 +- .../se/su/dsv/scipro/match/IdeaExport.java | 67 +- .../dsv/scipro/match/IdeaParticipation.java | 111 +- .../java/se/su/dsv/scipro/match/Keyword.java | 20 +- .../java/se/su/dsv/scipro/match/Match.java | 75 +- .../su/dsv/scipro/match/PreliminaryMatch.java | 78 +- .../java/se/su/dsv/scipro/match/Target.java | 4 +- .../milestones/dataobjects/Milestone.java | 77 +- .../MilestoneActivityTemplate.java | 170 +- .../dataobjects/MilestonePhaseTemplate.java | 69 +- .../service/MilestoneActivator.java | 2 +- .../nonworkperiod/NonWorkDayPeriod.java | 11 +- .../notifications/dataobject/CustomEvent.java | 4 + .../notifications/dataobject/GroupEvent.java | 44 +- .../notifications/dataobject/IdeaEvent.java | 31 +- .../dataobject/MileStoneEvent.java | 94 +- .../dataobject/Notification.java | 71 +- .../dataobject/NotificationEvent.java | 123 +- .../notifications/dataobject/PeerEvent.java | 34 +- .../dataobject/PeerRequestEvent.java | 6 + .../dataobject/ProjectEvent.java | 34 +- .../dataobject/ProjectForumEvent.java | 36 +- .../dataobject/SeminarEvent.java | 34 +- .../entities/DeliveryConfiguration.java | 13 +- .../java/se/su/dsv/scipro/peer/Answer.java | 108 +- .../java/se/su/dsv/scipro/peer/Comment.java | 16 +- .../se/su/dsv/scipro/peer/CommentThread.java | 9 +- .../se/su/dsv/scipro/peer/PeerRequest.java | 238 +- .../se/su/dsv/scipro/peer/PeerReview.java | 267 +- .../scipro/plagiarism/PlagiarismRequest.java | 49 +- .../plagiarism/urkund/UrkundSettings.java | 8 +- .../plagiarism/urkund/UrkundSubmission.java | 190 +- .../java/se/su/dsv/scipro/project/Author.java | 65 +- .../se/su/dsv/scipro/project/Project.java | 542 +-- .../scipro/projectpartner/ProjectPartner.java | 25 +- .../dsv/scipro/report/AbstractCriterion.java | 49 +- .../report/AbstractGradingCriterion.java | 189 +- .../report/AbstractGradingCriterionPoint.java | 79 +- .../dsv/scipro/report/AttachmentReport.java | 26 +- .../se/su/dsv/scipro/report/Criterion.java | 96 +- .../se/su/dsv/scipro/report/GradeLimit.java | 11 +- .../dsv/scipro/report/GradingCriterion.java | 165 +- .../scipro/report/GradingCriterionPoint.java | 52 +- .../report/GradingCriterionPointTemplate.java | 3 + .../report/GradingCriterionTemplate.java | 17 +- .../su/dsv/scipro/report/GradingReport.java | 89 +- .../scipro/report/GradingReportTemplate.java | 165 +- .../dsv/scipro/report/OppositionReport.java | 102 +- .../java/se/su/dsv/scipro/report/Report.java | 77 +- .../report/SupervisorGradingReport.java | 93 +- .../se/su/dsv/scipro/reviewing/Decision.java | 106 +- .../scipro/reviewing/ReviewerApproval.java | 70 +- .../reviewing/ReviewerDeadlineSettings.java | 6 +- .../dsv/scipro/reviewing/ReviewerTarget.java | 14 +- .../settings/dataobjects/UserProfile.java | 69 +- .../se/su/dsv/scipro/survey/Question.java | 17 +- .../java/se/su/dsv/scipro/survey/Survey.java | 11 +- .../se/su/dsv/scipro/survey/SurveyAnswer.java | 5 +- .../se/su/dsv/scipro/system/DomainObject.java | 4 +- .../java/se/su/dsv/scipro/system/Event.java | 28 +- .../dsv/scipro/system/ExternalResource.java | 12 +- .../se/su/dsv/scipro/system/FooterLink.java | 1 + .../se/su/dsv/scipro/system/Password.java | 11 +- .../java/se/su/dsv/scipro/system/Program.java | 16 +- .../se/su/dsv/scipro/system/ProjectType.java | 25 +- .../scipro/system/ProjectTypeSettings.java | 98 +- .../se/su/dsv/scipro/system/ResearchArea.java | 14 +- .../java/se/su/dsv/scipro/system/Unit.java | 14 +- .../java/se/su/dsv/scipro/system/User.java | 48 +- .../se/su/dsv/scipro/system/Username.java | 15 +- .../dsv/scipro/thesislink/ExternalLink.java | 122 +- .../dsv/scipro/workerthreads/WorkerData.java | 10 +- .../V391__harmonize_table_attribute_name.sql | 3222 +++++++++++++++++ .../service/MilestoneActivatorTest.java | 2 +- .../admin/panels/AdminProjectTypePanel.java | 8 +- .../su/dsv/scipro/checklists/AnswerPanel.java | 2 +- .../checklists/ChecklistOverviewPanel.java | 2 +- .../ChecklistOverviewPanel.utf8.properties | 2 +- .../scipro/checklists/TrafficLightPanel.java | 2 +- .../ProjectActiveParticipationListPanel.java | 2 +- .../grading/AbstractExaminationsPanel.java | 4 +- .../IndividualAuthorAssessmentPanel.java | 2 +- .../dsv/scipro/peer/DisplayQuestionPanel.java | 2 +- .../peer/DisplayQuestionPanel.properties | 2 +- .../checklists/TrafficLightPanelTest.java | 2 +- .../scipro/peer/DisplayQuestionPanelTest.java | 2 +- 129 files changed, 8653 insertions(+), 3217 deletions(-) create mode 100644 core/src/main/resources/db/migration/V391__harmonize_table_attribute_name.sql diff --git a/core/src/main/java/se/su/dsv/scipro/activityplan/Activity.java b/core/src/main/java/se/su/dsv/scipro/activityplan/Activity.java index 1f5182ca05..28e834f5ef 100755 --- a/core/src/main/java/se/su/dsv/scipro/activityplan/Activity.java +++ b/core/src/main/java/se/su/dsv/scipro/activityplan/Activity.java @@ -1,140 +1,164 @@ package se.su.dsv.scipro.activityplan; import com.querydsl.core.annotations.QueryInit; -import jakarta.persistence.GenerationType; -import se.su.dsv.scipro.checklist.Checklist; -import se.su.dsv.scipro.file.FileReference; -import se.su.dsv.scipro.system.LazyDeletableDomainObject; +import jakarta.persistence.Basic; +import jakarta.persistence.Table; import jakarta.persistence.Cacheable; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; +import jakarta.persistence.GenerationType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToOne; + +import se.su.dsv.scipro.checklist.Checklist; +import se.su.dsv.scipro.file.FileReference; +import se.su.dsv.scipro.system.LazyDeletableDomainObject; + import java.io.Serializable; -import java.util.*; +import java.util.Comparator; +import java.util.Date; +import java.util.Objects; @Entity +@Table(name = "activity") @Cacheable(true) public class Activity extends LazyDeletableDomainObject { - @Id + + public static IActivityPlan builder(){ + return new Builder(); + } + + //<editor-fold desc="Basic JPA-mappings"> + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(optional=false) - @JoinColumn (name="activityTemplate_id") - @QueryInit("project") - private ActivityPlan activityPlan; + @Basic + @Column(name = "title", nullable=false) + private String title; - @Column(nullable=false) - private Date date; + @Basic + @Column(name = "date", nullable=false) + private Date date; - @Column(nullable=false) - private String title; - - private String description; - - @OneToOne(optional = true, cascade = CascadeType.ALL) - @JoinColumn(name = "file_upload_reference_id") - private FileReference fileUpload; - - @ManyToOne - private Checklist checklist; + @Basic + @Column(name = "description") + private String description; + @Basic + @Column(name = "editable") private boolean editable = true; @Enumerated(EnumType.STRING) + @Column(name = "action") private Action action = Action.NONE; - + //</editor-fold> + + //<editor-fold desc="JPA-mappings of foreign keys in this table (activity) referencing other tables."> + @ManyToOne(optional = false) + @JoinColumn(name = "activity_plan_id", referencedColumnName = "id") + @QueryInit("project") + private ActivityPlan activityPlan; + + @ManyToOne + @JoinColumn(name = "checklist_id", referencedColumnName = "id") + private Checklist checklist; + + @OneToOne(optional = true, cascade = CascadeType.ALL) + @JoinColumn(name = "upload_file_reference_id", referencedColumnName = "id") + private FileReference fileUpload; + //</editor-fold> + + //<editor-fold desc="Constructor"> public Activity() { this.title = ""; this.description = ""; } + //</editor-fold> - @Override - public String toString(){ - return "Event: "+ getTitle()+"@"+getDate(); - } - - @Override + //<editor-fold desc="Properties (Getters and Setters)"> + @Override public Long getId() { return this.id; } - public ActivityPlan getActivityPlan() { - return this.activityPlan; - } - - public Date getDate() { - return this.date; - } - - public String getTitle() { - return this.title; - } - - public String getDescription() { - return this.description; - } - - public FileReference getFileUpload() { - return this.fileUpload; - } - - public Checklist getChecklist() { - return this.checklist; - } - - public boolean isEditable() { - return this.editable; - } - - public Action getAction() { - return this.action; - } - public void setId(Long id) { this.id = id; } - public void setActivityPlan(ActivityPlan activityPlan) { - this.activityPlan = activityPlan; - } - - public void setDate(Date date) { - this.date = date; + public String getTitle() { + return this.title; } public void setTitle(String title) { this.title = title; } + public Date getDate() { + return this.date; + } + + public void setDate(Date date) { + this.date = date; + } + + public String getDescription() { + return this.description; + } + public void setDescription(String description) { this.description = description; } - public void setFileUpload(FileReference fileUpload) { - this.fileUpload = fileUpload; - } - - public void setChecklist(Checklist checklist) { - this.checklist = checklist; + public boolean isEditable() { + return this.editable; } public void setEditable(boolean editable) { this.editable = editable; } + public Action getAction() { + return this.action; + } + public void setAction(Action action) { this.action = action; } + public ActivityPlan getActivityPlan() { + return this.activityPlan; + } + + public void setActivityPlan(ActivityPlan activityPlan) { + this.activityPlan = activityPlan; + } + + public Checklist getChecklist() { + return this.checklist; + } + + public void setChecklist(Checklist checklist) { + this.checklist = checklist; + } + + public FileReference getFileUpload() { + return this.fileUpload; + } + + public void setFileUpload(FileReference fileUpload) { + this.fileUpload = fileUpload; + } + //</editor-fold> + + //<editor-fold desc="Methods Common To All Objects"> @Override public boolean equals(final Object o) { if (o == this) return true; @@ -144,15 +168,24 @@ public class Activity extends LazyDeletableDomainObject { && Objects.equals(this.getId(), other.getId()); } - protected boolean canEqual(final Object other) { - return other instanceof Activity; + @Override + public int hashCode() { + return Objects.hashCode(getId()); } @Override - public int hashCode() { - return Objects.hashCode(getId()); - } + public String toString(){ + return "Event: "+ getTitle()+"@"+getDate(); + } + //</editor-fold> + //<editor-fold desc="Other methods"> + protected boolean canEqual(final Object other) { + return other instanceof Activity; + } + //</editor-fold> + + //<editor-fold desc="Nested types"> public static class ByDateComparator implements Comparator<Activity>, Serializable { @Override public int compare(Activity o1, Activity o2) { @@ -209,10 +242,6 @@ public class Activity extends LazyDeletableDomainObject { } } - public static IActivityPlan builder(){ - return new Builder(); - } - public interface IActivityPlan { IDate activityPlan(ActivityPlan activityPlan); } @@ -233,4 +262,5 @@ public class Activity extends LazyDeletableDomainObject { IBuild editable(boolean editable); Activity build(); } + //</editor-fold> } diff --git a/core/src/main/java/se/su/dsv/scipro/activityplan/ActivityPlan.java b/core/src/main/java/se/su/dsv/scipro/activityplan/ActivityPlan.java index 2ff8883bea..8af7cd3374 100755 --- a/core/src/main/java/se/su/dsv/scipro/activityplan/ActivityPlan.java +++ b/core/src/main/java/se/su/dsv/scipro/activityplan/ActivityPlan.java @@ -1,67 +1,92 @@ package se.su.dsv.scipro.activityplan; +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; + +import jakarta.persistence.Table; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.DomainObject; -import jakarta.persistence.*; import java.util.Date; import java.util.Objects; import java.util.Set; import java.util.TreeSet; @Entity +@Table(name ="activity_plan") @Cacheable(true) public class ActivityPlan extends DomainObject { + + public static IProject builder() { + return new Builder(); + } + + //<editor-fold desc="Basic JPA-mappings"> @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - + + @Basic + @Column(name = "start_date") + private Date startDate; + //</editor-fold> + + //<editor-fold desc="JPA-mappings of foreign keys in this table (activity_plan) referencing other tables"> + @OneToOne(optional=false) + @JoinColumn(name = "project_id", referencedColumnName = "id") + private Project project; + //</editor-fold> + + //<editor-fold desc="JPA-mappings of other tables referencing to this table "activity_plan"> @OneToMany(mappedBy= "activityPlan",cascade=CascadeType.PERSIST, orphanRemoval = true) private Set<Activity> activities = new TreeSet<>(new Activity.ByDateComparator()); - - @OneToOne(optional=false) - private Project project; - - private Date startDate; + //</editor-fold> + //<editor-fold desc="Properties (Getters and Setters)"> @Override public Long getId() { return this.id; } - public Set<Activity> getActivities() { - return this.activities; - } - - public Project getProject() { - return this.project; - } - - public Date getStartDate() { - return this.startDate; - } - public void setId(Long id) { this.id = id; } - public void setActivities(Set<Activity> activities) { - this.activities = activities; - } - - public void setProject(Project project) { - this.project = project; + public Date getStartDate() { + return this.startDate; } public void setStartDate(Date startDate) { this.startDate = startDate; } - @Override - public String toString() { - return "ActivityPlan(id=" + this.getId() + ", activities=" + this.getActivities() + ", project=" + this.getProject() + ", startDate=" + this.getStartDate() + ")"; + public Project getProject() { + return this.project; } + public void setProject(Project project) { + this.project = project; + } + + public Set<Activity> getActivities() { + return this.activities; + } + + public void setActivities(Set<Activity> activities) { + this.activities = activities; + } + //</editor-fold> + + //<editor-fold desc="Methods Common To All Objects"> @Override public boolean equals(final Object o) { if (o == this) return true; @@ -74,15 +99,25 @@ public class ActivityPlan extends DomainObject { && Objects.equals(this.getStartDate(), other.getStartDate()); } - protected boolean canEqual(final Object other) { - return other instanceof ActivityPlan; - } - @Override public int hashCode() { return Objects.hash(this.getId(), this.getActivities(), this.getProject(), this.getStartDate()); } + @Override + public String toString() { + return "ActivityPlan(id=" + this.getId() + ", activities=" + this.getActivities() + ", project=" + + this.getProject() + ", startDate=" + this.getStartDate() + ")"; + } + //</editor-fold> + + //<editor-fold desc="Other methods"> + protected boolean canEqual(final Object other) { + return other instanceof ActivityPlan; + } + //</editor-fold> + + //<editor-fold desc="Nested types" private static class Builder implements IProject, IBuild { private Project project; @@ -100,10 +135,6 @@ public class ActivityPlan extends DomainObject { } } - public static IProject builder() { - return new Builder(); - } - public interface IProject { IBuild project(Project project); } @@ -111,4 +142,5 @@ public class ActivityPlan extends DomainObject { public interface IBuild { ActivityPlan build(); } + //</editor-fold> } diff --git a/core/src/main/java/se/su/dsv/scipro/activityplan/ActivityPlanTemplate.java b/core/src/main/java/se/su/dsv/scipro/activityplan/ActivityPlanTemplate.java index 650393135d..b91217a705 100755 --- a/core/src/main/java/se/su/dsv/scipro/activityplan/ActivityPlanTemplate.java +++ b/core/src/main/java/se/su/dsv/scipro/activityplan/ActivityPlanTemplate.java @@ -1,98 +1,117 @@ package se.su.dsv.scipro.activityplan; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Lob; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OrderColumn; + +import jakarta.persistence.Table; import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; -import java.util.*; - @Entity +@Table(name = "activity_plan_template") @Cacheable(true) public class ActivityPlanTemplate extends DomainObject { + //<editor-fold desc="Basic JPA-mappings"> @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OrderColumn(name = "numberInOrder") - @OneToMany(mappedBy="activityPlanTemplate", orphanRemoval=true, cascade=CascadeType.ALL) - private List<ActivityTemplate> activityTemplates = new ArrayList<>(); - - public List<ActivityTemplate> getActivityTemplates(){ - return Collections.unmodifiableList(activityTemplates); - } - - public void setActivityTemplates(List<ActivityTemplate> activityTemplates){ - this.activityTemplates = new ArrayList<>(activityTemplates); - } - - @ManyToOne(optional=false) - private User creator; - - @Column(nullable=false) - private String title; - - @Lob - private String description; - - @Column(nullable=false) + @Basic + @Column(name = "is_sys_admin_template", nullable=false) private boolean isSysAdminTemplate = false; - public void addActivity(ActivityTemplate activity){ - activity.setActivityPlanTemplate(this); - activity.setNumberInOrder(activityTemplates.size()); - activityTemplates.add(activity); - } + @Basic + @Column(name = "title", nullable = false) + private String title; - public void clearActivities(){ - activityTemplates.clear(); - } + @Basic + @Column(name = "description") + @Lob + private String description; + //</editor-fold> - public void addActivities(final Collection<ActivityTemplate> activities){ - activityTemplates.addAll(activities); - } + //<editor-fold desc="JPA-mappings of foreign keys in this table (activity_plan_template) referencing other tables."> + @ManyToOne(optional = false) + @JoinColumn(name = "creator_user_id", referencedColumnName = "id") + private User creator; + //</editor-fold> - @Override + //<editor-fold desc="JPA-mappings of other tables referencing to this table 'activity_plan_template'"> + @OneToMany(mappedBy="activityPlanTemplate", orphanRemoval=true, cascade=CascadeType.ALL) + @OrderColumn(name = "number_in_order") + private List<ActivityTemplate> activityTemplates = new ArrayList<>(); + //</editor-fold> + + //<editor-fold desc="Properties (Getters and Setters)"> + @Override public Long getId() { return this.id; } - public User getCreator() { - return this.creator; - } - - public String getTitle() { - return this.title; - } - - public String getDescription() { - return this.description; - } - - public boolean isSysAdminTemplate() { - return this.isSysAdminTemplate; - } - public void setId(Long id) { this.id = id; } - public void setCreator(User creator) { - this.creator = creator; - } - - public void setTitle(String title) { - this.title = title; - } - - public void setDescription(String description) { - this.description = description; + public boolean isSysAdminTemplate() { + return this.isSysAdminTemplate; } public void setSysAdminTemplate(boolean isSysAdminTemplate) { this.isSysAdminTemplate = isSysAdminTemplate; } + public String getTitle() { + return this.title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return this.description; + } + + public void setDescription(String description) { + this.description = description; + } + + public User getCreator() { + return this.creator; + } + + public void setCreator(User creator) { + this.creator = creator; + } + + public List<ActivityTemplate> getActivityTemplates(){ + return Collections.unmodifiableList(activityTemplates); + } + + public void setActivityTemplates(List<ActivityTemplate> activityTemplates){ + this.activityTemplates = new ArrayList<>(activityTemplates); + } + //</editor-fold> + + //<editor-fold desc="Methods Common To All Objects"> @Override public boolean equals(final Object o) { if (o == this) return true; @@ -119,6 +138,25 @@ public class ActivityPlanTemplate extends DomainObject { @Override public String toString() { - return "ActivityPlanTemplate(id=" + this.getId() + ", creator=" + this.getCreator() + ", title=" + this.getTitle() + ", description=" + this.getDescription() + ", isSysAdminTemplate=" + this.isSysAdminTemplate() + ")"; + return "ActivityPlanTemplate(id=" + this.getId() + ", creator=" + this.getCreator() + + ", title=" + this.getTitle() + ", description=" + this.getDescription() + + ", isSysAdminTemplate=" + this.isSysAdminTemplate() + ")"; } + //</editor-fold> + + //<editor-fold desc="Other methods"> + public void addActivity(ActivityTemplate activity){ + activity.setActivityPlanTemplate(this); + activity.setNumberInOrder(activityTemplates.size()); + activityTemplates.add(activity); + } + + public void clearActivities(){ + activityTemplates.clear(); + } + + public void addActivities(final Collection<ActivityTemplate> activities){ + activityTemplates.addAll(activities); + } + //</editor-fold> } diff --git a/core/src/main/java/se/su/dsv/scipro/activityplan/ActivityTemplate.java b/core/src/main/java/se/su/dsv/scipro/activityplan/ActivityTemplate.java index c43c8a237c..6671bea897 100755 --- a/core/src/main/java/se/su/dsv/scipro/activityplan/ActivityTemplate.java +++ b/core/src/main/java/se/su/dsv/scipro/activityplan/ActivityTemplate.java @@ -1,116 +1,142 @@ package se.su.dsv.scipro.activityplan; +import java.util.Objects; + +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Lob; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; + import se.su.dsv.scipro.checklist.ChecklistTemplate; import se.su.dsv.scipro.system.DomainObject; -import jakarta.persistence.*; -import java.util.Objects; - @Entity +@Table(name = "activity_template") public class ActivityTemplate extends DomainObject { + //<editor-fold desc="Basic JPA-mappings"> @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(nullable = false) + @Basic + @Column(name = "title", nullable = false) private String title; + @Basic + @Column(name = "description") @Lob private String description; - @ManyToOne - private ActivityPlanTemplate activityPlanTemplate; - - @Column(nullable = false) + @Basic + @Column(name = "days_offset", nullable = false) private int daysOffset; + @Basic + @Column(name = "action") @Enumerated(EnumType.STRING) private Action action = Action.NONE; - @Column(nullable = false) + @Basic + @Column(name = "number_in_order", nullable = false) private int numberInOrder = Integer.MAX_VALUE; + //</editor-fold> + + //<editor-fold desc="JPA-mappings of foreign keys in this table (activity_template) referencing other tables."> + @ManyToOne + @JoinColumn(name = "activity_plan_template_id", referencedColumnName = "id") + private ActivityPlanTemplate activityPlanTemplate; @ManyToOne(optional = true) + @JoinColumn(name = "checklist_template_id", referencedColumnName = "id") private ChecklistTemplate checklistTemplate; + //</editor-fold> + //<editor-fold desc="Constructors"> public ActivityTemplate() { } public ActivityTemplate(int daysOffset) { this.daysOffset = daysOffset; } + //</editor-fold> - public int getDaysOffset() { - return daysOffset; - } - - public int getNumberInOrder() { - return numberInOrder; - } - + //<editor-fold desc="Properties (Getters and Setters"> @Override public Long getId() { return this.id; } - public String getTitle() { - return this.title; - } - - public String getDescription() { - return this.description; - } - - public ActivityPlanTemplate getActivityPlanTemplate() { - return this.activityPlanTemplate; - } - - public Action getAction() { - return this.action; - } - - public ChecklistTemplate getChecklistTemplate() { - return this.checklistTemplate; - } - public void setId(Long id) { this.id = id; } + public String getTitle() { + return this.title; + } + public void setTitle(String title) { this.title = title; } + public String getDescription() { + return this.description; + } + public void setDescription(String description) { this.description = description; } - public void setActivityPlanTemplate(ActivityPlanTemplate activityPlanTemplate) { - this.activityPlanTemplate = activityPlanTemplate; + public int getDaysOffset() { + return daysOffset; } public void setDaysOffset(int daysOffset) { this.daysOffset = daysOffset; } + public Action getAction() { + return this.action; + } + public void setAction(Action action) { this.action = action; } + public int getNumberInOrder() { + return numberInOrder; + } + public void setNumberInOrder(int numberInOrder) { this.numberInOrder = numberInOrder; } + public ActivityPlanTemplate getActivityPlanTemplate() { + return this.activityPlanTemplate; + } + + public void setActivityPlanTemplate(ActivityPlanTemplate activityPlanTemplate) { + this.activityPlanTemplate = activityPlanTemplate; + } + + public ChecklistTemplate getChecklistTemplate() { + return this.checklistTemplate; + } + public void setChecklistTemplate(ChecklistTemplate checklistTemplate) { this.checklistTemplate = checklistTemplate; } + //</editor-fold> - @Override - public String toString() { - return "ActivityTemplate(id=" + this.getId() + ", title=" + this.getTitle() + ", description=" + this.getDescription() + ", activityPlanTemplate=" + this.getActivityPlanTemplate() + ", daysOffset=" + this.getDaysOffset() + ", action=" + this.getAction() + ", numberInOrder=" + this.getNumberInOrder() + ", checklistTemplate=" + this.getChecklistTemplate() + ")"; - } - + //<editor-fold desc="Methods Common To All Objects"> @Override public boolean equals(final Object o) { if (o == this) return true; @@ -120,12 +146,24 @@ public class ActivityTemplate extends DomainObject { && Objects.equals(this.getId(), other.getId()); } - protected boolean canEqual(final Object other) { - return other instanceof ActivityTemplate; - } - @Override public int hashCode() { return Objects.hashCode(this.getId()); } -} \ No newline at end of file + + @Override + public String toString() { + return "ActivityTemplate(id=" + this.getId() + ", title=" + this.getTitle() + + ", description=" + this.getDescription() + ", activityPlanTemplate=" + + this.getActivityPlanTemplate() + ", daysOffset=" + this.getDaysOffset() + ", action=" + + this.getAction() + ", numberInOrder=" + this.getNumberInOrder() + ", checklistTemplate=" + + this.getChecklistTemplate() + ")"; + } + //</editor-fold> + + //<editor-fold desc="Other methods"> + protected boolean canEqual(final Object other) { + return other instanceof ActivityTemplate; + } + //</editor-fold> +} diff --git a/core/src/main/java/se/su/dsv/scipro/checklist/Checklist.java b/core/src/main/java/se/su/dsv/scipro/checklist/Checklist.java index 3d25b8b1c1..d4c7044f52 100755 --- a/core/src/main/java/se/su/dsv/scipro/checklist/Checklist.java +++ b/core/src/main/java/se/su/dsv/scipro/checklist/Checklist.java @@ -1,12 +1,33 @@ package se.su.dsv.scipro.checklist; - +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.CascadeType; +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.MapKeyJoinColumn; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; -import java.util.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; @Entity @Table(name = "checklist") @@ -17,6 +38,7 @@ public class Checklist extends DomainObject { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Basic @Column(nullable = false) private String name; @@ -28,15 +50,26 @@ public class Checklist extends DomainObject { */ @Deprecated @ManyToOne(optional = false) + @JoinColumn(name = "project_id") private Project project; @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinTable(name = "checklist_checklist_question", + joinColumns = @JoinColumn(name = "checklist_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "checklist_question_id", referencedColumnName = "id")) private List<ChecklistQuestion> questions = new ArrayList<>(); @ManyToMany + @JoinTable(name = "checklist_checklist_category", + joinColumns = @JoinColumn(name = "checklist_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "checklist_category_id", referencedColumnName = "id")) private List<se.su.dsv.scipro.checklist.ChecklistCategory> categories = new ArrayList<>(); @ElementCollection(fetch = FetchType.EAGER) + @CollectionTable(name = "checklist_user_last_open_date", joinColumns = @JoinColumn(name = "checklist_id")) + @Column(name = "last_open_date") + @SuppressWarnings("JpaDataSourceORMInspection") // false warning from IntelliJ for the @MapKeyJoinColumn + @MapKeyJoinColumn(name = "user_id") private Map<User, Date> userLastOpenDate = new HashMap<>(); protected Checklist() { diff --git a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistAnswer.java b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistAnswer.java index 05d756e6a1..704f907f40 100755 --- a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistAnswer.java +++ b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistAnswer.java @@ -1,29 +1,54 @@ package se.su.dsv.scipro.checklist; +import java.util.Objects; + +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Lob; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; + import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; -import java.util.Objects; - @Entity @Table(name = "checklist_answer") public class ChecklistAnswer extends DomainObject { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Basic + @Column(name = "answer", nullable = false) @Enumerated(EnumType.STRING) - @Column(nullable = false) private ChecklistAnswerEnum answer; - @ManyToOne(optional = false) - private User user; - + @Basic + @Column(name = "comment") @Lob - @Column private String comment; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (checklist_answer) referencing other + // tables. + // ---------------------------------------------------------------------------------- + @ManyToOne(optional = false) + @JoinColumn(name = "user_id", referencedColumnName = "id") + private User user; + + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- protected ChecklistAnswer() { } @@ -36,44 +61,45 @@ public class ChecklistAnswer extends DomainObject { this.answer = answer != null ? answer : ChecklistAnswerEnum.NO_ANSWER; } + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- @Override public Long getId() { return this.id; } - public ChecklistAnswerEnum getAnswer() { - return this.answer; - } - - public User getUser() { - return this.user; - } - - public String getComment() { - return this.comment; - } - public void setId(Long id) { this.id = id; } + public ChecklistAnswerEnum getAnswer() { + return this.answer; + } + public void setAnswer(ChecklistAnswerEnum answer) { this.answer = answer; } - public void setUser(User user) { - this.user = user; + public String getComment() { + return this.comment; } public void setComment(String comment) { this.comment = comment; } - @Override - public String toString() { - return "ChecklistAnswer(id=" + this.getId() + ", answer=" + this.getAnswer() + ", user=" + this.getUser() + ", comment=" + this.getComment() + ")"; + public User getUser() { + return this.user; } + public void setUser(User user) { + this.user = user; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -83,12 +109,21 @@ public class ChecklistAnswer extends DomainObject { && Objects.equals(this.getId(), other.getId()); } - protected boolean canEqual(final Object other) { - return other instanceof ChecklistAnswer; - } - @Override public int hashCode() { return Objects.hashCode(this.getId()); } + + @Override + public String toString() { + return "ChecklistAnswer(id=" + this.getId() + ", answer=" + this.getAnswer() + ", user=" + this.getUser() + + ", comment=" + this.getComment() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof ChecklistAnswer; + } } \ No newline at end of file diff --git a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistAnswerEnum.java b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistAnswerEnum.java index 796d0ddeeb..e806794440 100755 --- a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistAnswerEnum.java +++ b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistAnswerEnum.java @@ -4,6 +4,6 @@ public enum ChecklistAnswerEnum { RED, GREEN, YELLOW, - NOT_APLICABLE, + NOT_APPLICABLE, NO_ANSWER } diff --git a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistCategory.java b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistCategory.java index ed0f76c658..c3589be745 100755 --- a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistCategory.java +++ b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistCategory.java @@ -1,13 +1,17 @@ -/** - * - */ package se.su.dsv.scipro.checklist; -import se.su.dsv.scipro.system.DomainObject; - -import jakarta.persistence.*; import java.util.Objects; +import jakarta.persistence.Cacheable; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +import se.su.dsv.scipro.system.DomainObject; + @Entity @Table(name="checklist_category") @Cacheable(true) @@ -16,7 +20,7 @@ public class ChecklistCategory extends DomainObject { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(unique=true) + @Column(name = "category_name", unique = true) private String categoryName; protected ChecklistCategory() { diff --git a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistQuestion.java b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistQuestion.java index 337551dc04..3678024780 100755 --- a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistQuestion.java +++ b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistQuestion.java @@ -1,13 +1,26 @@ package se.su.dsv.scipro.checklist; -import se.su.dsv.scipro.system.DomainObject; -import se.su.dsv.scipro.system.User; - -import jakarta.persistence.*; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.Lob; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; + +import se.su.dsv.scipro.system.DomainObject; +import se.su.dsv.scipro.system.User; + @Entity @Table(name = "checklist_question") @Cacheable(true) @@ -20,13 +33,15 @@ public class ChecklistQuestion extends DomainObject { @Column(nullable = false) private String question; - @Column(nullable = false) + @Basic + @Column(name = "question_number", nullable = false) private int questionNumber; @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) @JoinTable( - joinColumns = @JoinColumn(name = "checklist_question_id") - ) + name = "checklist_question_checklist_answer", + joinColumns = @JoinColumn(name = "checklist_question_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "checklist_answer_id", referencedColumnName = "id")) private List<ChecklistAnswer> answers = new ArrayList<>(); protected ChecklistQuestion() { diff --git a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistTemplate.java b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistTemplate.java index 05b09733b1..12ad047041 100755 --- a/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistTemplate.java +++ b/core/src/main/java/se/su/dsv/scipro/checklist/ChecklistTemplate.java @@ -1,11 +1,27 @@ package se.su.dsv.scipro.checklist; +import jakarta.persistence.Basic; +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.ProjectType; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; @Entity @Table(name = "checklist_template") @@ -17,35 +33,42 @@ public class ChecklistTemplate extends DomainObject { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Basic @Column(nullable = false) private String name; @Basic(optional = true) + @Column(name = "description") private String description; - @Column + @Basic + @Column(name = "template_number") private int templateNumber = DEFAULT_TEMPLATE_NUMBER; - @Lob @ElementCollection + @CollectionTable(name = "checklist_template_question", + joinColumns = @JoinColumn(name = "checklist_template_id")) + @Column(name = "question") private List<String> questions = new ArrayList<>(1); @ManyToOne(optional = false) + @JoinColumn(name = "creator_user_id", referencedColumnName = "id") private User creator; @ManyToMany - @JoinTable( - joinColumns = @JoinColumn(name = "checklist_template_id") - ) + @JoinTable(name = "checklist_template_checklist_category", + joinColumns = @JoinColumn(name = "checklist_template_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "checklist_category_id", referencedColumnName = "id")) private List<ChecklistCategory> categories = new ArrayList<>(); @ManyToMany - @JoinTable(name = "checklist_template_ProjectType", + @JoinTable(name = "checklist_template_project_type", joinColumns = {@JoinColumn(name = "checklist_template_id")}, - inverseJoinColumns = {@JoinColumn(name = "projectType_id")}) + inverseJoinColumns = {@JoinColumn(name = "project_type_id")}) private Collection<ProjectType> projectTypes = new HashSet<>(); public ChecklistTemplate() { + } public ChecklistTemplate(String name, User creator) { diff --git a/core/src/main/java/se/su/dsv/scipro/file/FileDescription.java b/core/src/main/java/se/su/dsv/scipro/file/FileDescription.java index 7b4060922b..ac42cab487 100755 --- a/core/src/main/java/se/su/dsv/scipro/file/FileDescription.java +++ b/core/src/main/java/se/su/dsv/scipro/file/FileDescription.java @@ -33,25 +33,40 @@ public class FileDescription extends DomainObject { public static final int FILES_PER_SUBDIRECTORY = 1000; public static final String FILE_ROOT = "/scipro-files"; + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column + @Basic + @Column(name = "name") private String name; - @Column + @Basic + @Column(name = "mime_type") private String mimeType; - @Column - private String identifier; - - @ManyToOne - @JoinColumn(name = "userId") - private User uploader; - + @Basic + @Column(name = "size") private long size; + @Basic + @Column(name = "file_identifier") + private String identifier; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (file_description) referencing + // other tables. + // ---------------------------------------------------------------------------------- + @ManyToOne + @JoinColumn(name = "user_id", referencedColumnName = "id") + private User uploader; + + // ---------------------------------------------------------------------------------- + // JPA lifecycle methods + // ---------------------------------------------------------------------------------- @PostRemove void removeActualData() { try { @@ -63,6 +78,96 @@ public class FileDescription extends DomainObject { } } + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- + @Override + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getMimeType() { + return this.mimeType; + } + + public void setMimeType(String mimeType) { + this.mimeType = mimeType; + } + + public long getSize() { + return this.size; + } + + public void setSize(long size) { + this.size = size; + } + + public String getIdentifier() { + return this.identifier; + } + + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + public User getUploader() { + return this.uploader; + } + + public void setUploader(User uploader) { + this.uploader = uploader; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- + @Override + public boolean equals(final Object o) { + if (o == this) return true; + if (!(o instanceof FileDescription)) return false; + final FileDescription other = (FileDescription) o; + return other.canEqual(this) + && Objects.equals(this.getId(), other.getId()); + } + + @Override + public int hashCode() { + final int PRIME = 59; + int result = 1; + final Object $id = this.getId(); + result = result * PRIME + ($id == null ? 43 : $id.hashCode()); + return result; + } + + // Todo + @Override + public String toString() { + if (name != null) { + return name; + } else { + return super.toString(); + } + } + + // ---------------------------------------------------------------------------------- + // Other methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof FileDescription; + } + public Path getPath0() { return FileSystems.getDefault().getPath(FILE_ROOT, getSubdirectory(), Long.toString(id)); } @@ -78,85 +183,4 @@ public class FileDescription extends DomainObject { public InputStream getData() throws IOException { return Files.newInputStream(getPath0()); } - - public String getName() { - return name; - } - - // Todo - @Override - public String toString() { - if (name != null) { - return name; - } else { - return super.toString(); - } - } - - @Override - public Long getId() { - return this.id; - } - - public String getMimeType() { - return this.mimeType; - } - - public String getIdentifier() { - return this.identifier; - } - - public User getUploader() { - return this.uploader; - } - - public long getSize() { - return this.size; - } - - public void setId(Long id) { - this.id = id; - } - - public void setName(String name) { - this.name = name; - } - - public void setMimeType(String mimeType) { - this.mimeType = mimeType; - } - - public void setIdentifier(String identifier) { - this.identifier = identifier; - } - - public void setUploader(User uploader) { - this.uploader = uploader; - } - - public void setSize(long size) { - this.size = size; - } - - @Override - public boolean equals(final Object o) { - if (o == this) return true; - if (!(o instanceof FileDescription)) return false; - final FileDescription other = (FileDescription) o; - return other.canEqual(this) - && Objects.equals(this.getId(), other.getId()); - } - - protected boolean canEqual(final Object other) { - return other instanceof FileDescription; - } - - @Override - public int hashCode() { - final int PRIME = 59; - int result = 1; - final Object $id = this.getId(); - result = result * PRIME + ($id == null ? 43 : $id.hashCode()); - return result; - } } diff --git a/core/src/main/java/se/su/dsv/scipro/file/FileReference.java b/core/src/main/java/se/su/dsv/scipro/file/FileReference.java index 34f7ce0beb..4858d090db 100644 --- a/core/src/main/java/se/su/dsv/scipro/file/FileReference.java +++ b/core/src/main/java/se/su/dsv/scipro/file/FileReference.java @@ -9,7 +9,7 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; import java.io.Serializable; -import java.util.*; +import java.util.Objects; /** * A reference to a file. @@ -29,7 +29,7 @@ public class FileReference implements Serializable { private Long id; @ManyToOne(cascade = CascadeType.PERSIST) - @JoinColumn(name = "file_description_id") + @JoinColumn(name = "file_description_id", referencedColumnName = "id") private FileDescription fileDescription; public Long getId() { diff --git a/core/src/main/java/se/su/dsv/scipro/file/ProjectFile.java b/core/src/main/java/se/su/dsv/scipro/file/ProjectFile.java index d63c05d4d0..ba57470626 100644 --- a/core/src/main/java/se/su/dsv/scipro/file/ProjectFile.java +++ b/core/src/main/java/se/su/dsv/scipro/file/ProjectFile.java @@ -1,71 +1,88 @@ package se.su.dsv.scipro.file; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.DomainObject; -import jakarta.persistence.*; import java.util.Objects; @Entity @Table(name = "project_file") public class ProjectFile extends DomainObject { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne - private Project project; - + @Basic + @Column(name = "file_source") @Enumerated(EnumType.STRING) private FileSource fileSource = FileSource.FILES; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (project_file) referencing other tables. + // ---------------------------------------------------------------------------------- + @ManyToOne + @JoinColumn(name = "project_id", referencedColumnName = "id") + private Project project; + @OneToOne - @JoinColumn(name = "file_reference_id") + @JoinColumn(name = "file_reference_id", referencedColumnName = "id") private FileReference fileReference; + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- @Override public Long getId() { return this.id; } - public Project getProject() { - return this.project; - } - - public FileSource getFileSource() { - return this.fileSource; - } - - public FileDescription getFileDescription() { - return this.fileReference.getFileDescription(); - } - public void setId(Long id) { this.id = id; } - public void setProject(Project project) { - this.project = project; + public FileSource getFileSource() { + return this.fileSource; } public void setFileSource(FileSource fileSource) { this.fileSource = fileSource; } - public void setFileReference(FileReference fileReference) { - this.fileReference = fileReference; - } - public FileReference getFileReference() { return this.fileReference; } - @Override - public String toString() { - return "ProjectFile(id=" + this.getId() + ", project=" + this.getProject() + ", fileSource=" + this.getFileSource() + ", fileDescription=" + this.getFileDescription() + ")"; + public void setFileReference(FileReference fileReference) { + this.fileReference = fileReference; } + public Project getProject() { + return this.project; + } + + public void setProject(Project project) { + this.project = project; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -79,12 +96,24 @@ public class ProjectFile extends DomainObject { && Objects.equals(this.getFileDescription(), other.getFileDescription()); } - protected boolean canEqual(final Object other) { - return other instanceof ProjectFile; - } - @Override public int hashCode() { return Objects.hash(this.getId(), this.getProject(), this.getFileSource(), this.getFileDescription()); } + + @Override + public String toString() { + return "ProjectFile(id=" + this.getId() + ", project=" + this.getProject() + ", fileSource=" + this.getFileSource() + ", fileDescription=" + this.getFileDescription() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof ProjectFile; + } + + public FileDescription getFileDescription() { + return this.fileReference.getFileDescription(); + } } diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminar.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminar.java index 461be0f88c..1679e993a0 100755 --- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminar.java +++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminar.java @@ -23,7 +23,15 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.OneToMany; import jakarta.persistence.OneToOne; import jakarta.persistence.Table; -import java.util.*; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; @Entity @Table(name = "final_seminar") @@ -35,27 +43,69 @@ public class FinalSeminar extends LazyDeletableDomainObject { public static final int DEFAULT_MAX_PARTICIPANTS = 5; public static final String FINAL_SEMINAR = "finalSeminar"; + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToOne(optional = false) - @QueryInit({"projectType", "headSupervisor"}) - private Project project; - @Basic(optional = false) + @Column(name = "start_date") private Date startDate; @Basic(optional = false) + @Column(name = "room") private String room; + @Basic + @Column(name = "max_opponents") + private int maxOpponents = DEFAULT_MAX_OPPONENTS; + + @Basic + @Column(name = "max_participants") + private int maxParticipants = DEFAULT_MAX_PARTICIPANTS; + + @Enumerated(EnumType.STRING) + @Column(name = "presentation_lang") + private Language presentationLanguage; + + @Basic + @Column(name = "document_upload_date") + private Date documentUploadDate; + @Basic @Column(name = "extra_info") private String extraInfo; @Basic + @Column(name = "creation_reason") + private String creationReason; + + @Basic + @Column(name = "manual_participants") private Boolean manualParticipants = false; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (final_seminar) referencing other tables. + // ---------------------------------------------------------------------------------- + /* + * Cascading delete, set document to nul will delete the filedescription but + * not the actual file. Use FinarSeminarUploadController.deleteSeminarReport + * to delete the document + */ + @OneToOne(cascade = CascadeType.ALL) + @JoinColumn(name = "document_file_reference_id", referencedColumnName = "id") + private FileReference document; + + @OneToOne(optional = false) + @JoinColumn(name = "project_id", referencedColumnName = "id") + @QueryInit({"projectType", "headSupervisor"}) + private Project project; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of other tables referencing to this table "final_seminar" + // ---------------------------------------------------------------------------------- @OneToMany(mappedBy = FINAL_SEMINAR, orphanRemoval = true, cascade = CascadeType.ALL) private Set<FinalSeminarActiveParticipation> activeParticipations = new HashSet<>(); @@ -65,28 +115,10 @@ public class FinalSeminar extends LazyDeletableDomainObject { @OneToMany(mappedBy = FINAL_SEMINAR, orphanRemoval = true, cascade = CascadeType.ALL) private Set<FinalSeminarRespondent> respondents = new HashSet<>(); - /* - * Cascading delete, set document to nul will delete the filedescription but - * not the actual file. Use FinarSeminarUploadController.deleteSeminarReport - * to delete the document - */ - @OneToOne(cascade = CascadeType.ALL) - @JoinColumn(name = "document_reference_id") - private FileReference document; - - private Date documentUploadDate; - - @Enumerated(EnumType.STRING) - private Language presentationLanguage; - - private int maxOpponents = DEFAULT_MAX_OPPONENTS; - private int maxParticipants = DEFAULT_MAX_PARTICIPANTS; - - @Basic - private String creationReason; - + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- public FinalSeminar() { - } public FinalSeminar(int maxOpponents, int maxParticipants) { @@ -99,6 +131,90 @@ public class FinalSeminar extends LazyDeletableDomainObject { this.project = project; } + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- + @Override + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public boolean isCancelled() { + return isDeleted(); + } + + public void setCancelled(boolean cancelled) { + setDeleted(cancelled); + } + + public Date getStartDate() { + return this.startDate; + } + + public void setStartDate(Date startDate) { + this.startDate = (Date) startDate.clone(); + } + + public String getRoom() { + return this.room; + } + + public void setRoom(String room) { + this.room = room; + } + + public int getMaxOpponents() { + return this.maxOpponents; + } + + public void setMaxOpponents(int maxOpponents) { + this.maxOpponents = maxOpponents; + } + + public int getMaxParticipants() { + return this.maxParticipants; + } + + public void setMaxParticipants(int maxParticipants) { + this.maxParticipants = maxParticipants; + } + + public Language getPresentationLanguage() { + return this.presentationLanguage; + } + + public void setPresentationLanguage(Language presentationLanguage) { + this.presentationLanguage = presentationLanguage; + } + + public Date getDocumentUploadDate() { + return this.documentUploadDate; + } + + public void setDocumentUploadDate(Date documentUploadDate) { + this.documentUploadDate = documentUploadDate; + } + + public String getExtraInfo() { + return extraInfo; + } + + public void setExtraInfo(String extraInfo) { + this.extraInfo = extraInfo; + } + + public String getCreationReason() { + return this.creationReason; + } + + public void setCreationReason(String creationReason) { + this.creationReason = creationReason; + } + public Boolean getManualParticipants() { return manualParticipants; } @@ -107,21 +223,83 @@ public class FinalSeminar extends LazyDeletableDomainObject { this.manualParticipants = manualParticipants; } - public void setStartDate(Date startDate) { - this.startDate = (Date) startDate.clone(); + public FileReference getDocument() { + return this.document; + } + + public void setDocument(FileReference document) { + this.document = document; } public Project getProject() { return project; } + public void setProject(Project project) { + this.project = project; + } + + public Set<FinalSeminarActiveParticipation> getActiveParticipations() { + return Collections.unmodifiableSet(activeParticipations); + } + public void setActiveParticipations(Collection<FinalSeminarActiveParticipation> activeParticipations) { this.activeParticipations.clear(); this.activeParticipations.addAll(activeParticipations); } - public Set<FinalSeminarActiveParticipation> getActiveParticipations() { - return Collections.unmodifiableSet(activeParticipations); + public Set<FinalSeminarOpposition> getOppositions() { + return Collections.unmodifiableSet(oppositions); + } + + public void setOppositions(Collection<FinalSeminarOpposition> oppositions) { + this.oppositions.clear(); + this.oppositions.addAll(oppositions); + } + + public Set<FinalSeminarRespondent> getRespondents() { + return this.respondents; + } + + public void setRespondents(Set<FinalSeminarRespondent> respondents) { + this.respondents = respondents; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- + @Override + public boolean equals(final Object o) { + if (o == this) return true; + if (!(o instanceof FinalSeminar)) return false; + final FinalSeminar other = (FinalSeminar) o; + return other.canEqual(this) + && super.equals(o) + && Objects.equals(this.getId(), other.getId()); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.getId()); + } + + @Override + public String toString() { + return "FinalSeminar(id=" + this.getId() + ", project=" + this.getProject() + ", startDate=" + + this.getStartDate() + ", room=" + this.getRoom() + ", activeParticipations=" + + this.getActiveParticipations() + ", oppositions=" + this.getOppositions() + + ", respondents=" + this.getRespondents() + ", document=" + this.getDocument() + + ", documentUploadDate=" + this.getDocumentUploadDate() + ", presentationLanguage=" + + this.getPresentationLanguage() + ", maxOpponents=" + this.getMaxOpponents() + + ", maxParticipants=" + this.getMaxParticipants() + ", creationReason=" + + this.getCreationReason() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof FinalSeminar; } public void addActiveParticipant(FinalSeminarActiveParticipation participation) { @@ -132,25 +310,62 @@ public class FinalSeminar extends LazyDeletableDomainObject { this.activeParticipations.remove(participation); } - public void setOppositions(Collection<FinalSeminarOpposition> oppositions) { - this.oppositions.clear(); - this.oppositions.addAll(oppositions); + public void removeActiveParticipant(User user) { + activeParticipations.removeIf(next -> next.getUser().equals(user)); } - public Set<FinalSeminarOpposition> getOppositions() { - return Collections.unmodifiableSet(oppositions); + public Set<User> getActiveParticipants(){ + Set<User> activeParticipants = new HashSet<>(); + for (FinalSeminarActiveParticipation fsap : activeParticipations){ + activeParticipants.add(fsap.getUser()); + } + return activeParticipants; + } + + public Collection<User> getNotGradedActiveParticipations() { + return getNotGradedParticipations(activeParticipations); } public void addOpposition(FinalSeminarOpposition opposition) { this.oppositions.add(opposition); } + public void removeOpposition(FinalSeminarOpposition opposition) { + this.oppositions.remove(opposition); + } + + public Set<User> getOpponents(){ + Set<User> opponents = new HashSet<>(); + for (FinalSeminarOpposition fso : oppositions){ + opponents.add(fso.getUser()); + } + return opponents; + } + + public Collection<User> getNotGradedOpponents() { + return getNotGradedParticipations(oppositions); + } + + public Collection<User> getNotGradedRespondents() { + return getNotGradedParticipations(respondents); + } + + private Collection<User> getNotGradedParticipations(Set<? extends FinalSeminarParticipation> participations) { + List<User> result = new ArrayList<>(); + for (FinalSeminarParticipation participation : participations) { + if(participation.getGrade() == null) { + result.add(participation.getUser()); + } + } + return result; + } + public int getMinOpponents() { - return project.getMinOpponentsOnFinalSeminar(); + return getProject().getMinOpponentsOnFinalSeminar(); } public int getMinActiveParticipants() { - return project.getMinFinalSeminarActiveParticipation(); + return getProject().getMinFinalSeminarActiveParticipation(); } public List<Member> getMembers() { @@ -172,177 +387,10 @@ public class FinalSeminar extends LazyDeletableDomainObject { } public ProjectType getProjectType() { - return project.getProjectType(); + return getProject().getProjectType(); } public String getProjectTitle() { - return project.getTitle(); + return getProject().getTitle(); } - - public void setCancelled(boolean cancelled) { - setDeleted(cancelled); - } - - public boolean isCancelled() { - return isDeleted(); - } - - public void removeOpposition(FinalSeminarOpposition opposition) { - this.oppositions.remove(opposition); - } - - public Collection<User> getNotGradedOpponents() { - return getNotGradedParticipations(oppositions); - } - - public Collection<User> getNotGradedActiveParticipations() { - return getNotGradedParticipations(activeParticipations); - } - - public Collection<User> getNotGradedRespondents() { - return getNotGradedParticipations(respondents); - } - - private Collection<User> getNotGradedParticipations(Set<? extends FinalSeminarParticipation> participations) { - List<User> result = new ArrayList<>(); - for (FinalSeminarParticipation participation : participations) { - if(participation.getGrade() == null) { - result.add(participation.getUser()); - } - } - return result; - } - - public Set<User> getOpponents(){ - Set<User> opponents = new HashSet<>(); - for (FinalSeminarOpposition fso : oppositions){ - opponents.add(fso.getUser()); - } - return opponents; - } - - public Set<User> getActiveParticipants(){ - Set<User> activeParticipants = new HashSet<>(); - for (FinalSeminarActiveParticipation fsap : activeParticipations){ - activeParticipants.add(fsap.getUser()); - } - return activeParticipants; - } - - public void removeActiveParticipant(User user) { - activeParticipations.removeIf(next -> next.getUser().equals(user)); - } - - @Override - public Long getId() { - return this.id; - } - - public Date getStartDate() { - return this.startDate; - } - - public String getRoom() { - return this.room; - } - - public Set<FinalSeminarRespondent> getRespondents() { - return this.respondents; - } - - public FileReference getDocument() { - return this.document; - } - - public Date getDocumentUploadDate() { - return this.documentUploadDate; - } - - public Language getPresentationLanguage() { - return this.presentationLanguage; - } - - public int getMaxOpponents() { - return this.maxOpponents; - } - - public int getMaxParticipants() { - return this.maxParticipants; - } - - public void setId(Long id) { - this.id = id; - } - - public void setProject(Project project) { - this.project = project; - } - - public void setRoom(String room) { - this.room = room; - } - - public void setRespondents(Set<FinalSeminarRespondent> respondents) { - this.respondents = respondents; - } - - public void setDocument(FileReference document) { - this.document = document; - } - - public void setDocumentUploadDate(Date documentUploadDate) { - this.documentUploadDate = documentUploadDate; - } - - public void setPresentationLanguage(Language presentationLanguage) { - this.presentationLanguage = presentationLanguage; - } - - public void setMaxOpponents(int maxOpponents) { - this.maxOpponents = maxOpponents; - } - - public void setMaxParticipants(int maxParticipants) { - this.maxParticipants = maxParticipants; - } - - public void setCreationReason(String creationReason) { - this.creationReason = creationReason; - } - - public String getExtraInfo() { - return extraInfo; - } - - public void setExtraInfo(String extraInfo) { - this.extraInfo = extraInfo; - } - - @Override - public String toString() { - return "FinalSeminar(id=" + this.getId() + ", project=" + this.getProject() + ", startDate=" + this.getStartDate() + ", room=" + this.getRoom() + ", activeParticipations=" + this.getActiveParticipations() + ", oppositions=" + this.getOppositions() + ", respondents=" + this.getRespondents() + ", document=" + this.getDocument() + ", documentUploadDate=" + this.getDocumentUploadDate() + ", presentationLanguage=" + this.getPresentationLanguage() + ", maxOpponents=" + this.getMaxOpponents() + ", maxParticipants=" + this.getMaxParticipants() + ", creationReason=" + this.getCreationReason() + ")"; - } - - @Override - public boolean equals(final Object o) { - if (o == this) return true; - if (!(o instanceof FinalSeminar)) return false; - final FinalSeminar other = (FinalSeminar) o; - return other.canEqual(this) - && super.equals(o) - && Objects.equals(this.getId(), other.getId()); - } - - protected boolean canEqual(final Object other) { - return other instanceof FinalSeminar; - } - - @Override - public int hashCode() { - return Objects.hashCode(this.getId()); - } - - public String getCreationReason() { - return this.creationReason; - } -} \ No newline at end of file +} diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarActiveParticipation.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarActiveParticipation.java index 4930b37979..fdc7bf1429 100755 --- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarActiveParticipation.java +++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarActiveParticipation.java @@ -1,5 +1,6 @@ package se.su.dsv.scipro.finalseminar; +import jakarta.persistence.JoinColumn; import se.su.dsv.scipro.project.Project; import jakarta.persistence.Cacheable; @@ -9,13 +10,20 @@ import jakarta.persistence.Table; import java.util.Objects; @Entity -@Cacheable(true) @Table(name = "final_seminar_active_participation") +@Cacheable(true) public class FinalSeminarActiveParticipation extends FinalSeminarParticipation { - + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (final_seminar_active_participation) + // referencing other tables. + // ---------------------------------------------------------------------------------- @ManyToOne(optional = false) + @JoinColumn(name = "project_id", referencedColumnName = "id") private Project project; + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public Project getProject() { return this.project; } @@ -24,6 +32,9 @@ public class FinalSeminarActiveParticipation extends FinalSeminarParticipation { this.project = project; } + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -34,13 +45,16 @@ public class FinalSeminarActiveParticipation extends FinalSeminarParticipation { && Objects.equals(this.project, other.project); } - @Override - protected boolean canEqual(final Object other) { - return other instanceof FinalSeminarActiveParticipation; - } - @Override public int hashCode() { return Objects.hash(super.hashCode(), this.getProject()); } + + // ---------------------------------------------------------------------------------- + // Other methods + // ---------------------------------------------------------------------------------- + @Override + protected boolean canEqual(final Object other) { + return other instanceof FinalSeminarActiveParticipation; + } } diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOpposition.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOpposition.java index 65cf89e756..de9c6cd3a4 100755 --- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOpposition.java +++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOpposition.java @@ -13,73 +13,90 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToOne; import jakarta.persistence.Table; -import java.util.*; + +import java.util.Objects; @Entity @Table(name="final_seminar_opposition") public class FinalSeminarOpposition extends FinalSeminarParticipation { - public static final int FEEDBACK_LENGTH = 2000; - @ManyToOne(optional = false) - private Project project; - - @OneToOne - @JoinColumn(name = "opponent_report_reference_id") - private FileReference opponentReport; - - @OneToOne(optional = true, orphanRemoval = true, cascade = CascadeType.ALL, mappedBy = "finalSeminarOpposition") - private OppositionReport oppositionReport; + private static final int FEEDBACK_LENGTH = 2000; + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Basic + @Column(name = "points") private Integer points; @Basic - @Column(length = FEEDBACK_LENGTH) + @Column(name = "feedback", length = FEEDBACK_LENGTH) private String feedback; - public ProjectType getProjectType() { - return getFinalSeminar().getProject().getProjectType(); - } + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (final_seminar_opposition) referencing + // other tables. + // ---------------------------------------------------------------------------------- + @OneToOne + @JoinColumn(name = "opponent_report_file_reference_id", referencedColumnName = "id") + private FileReference opponentReport; - public void setProject(final Project project) { - this.project = project; - } + @ManyToOne(optional = false) + @JoinColumn(name = "project_id", referencedColumnName = "id") + private Project project; - public Project getProject() { - return this.project; - } - - public FileReference getOpponentReport() { - return this.opponentReport; - } - - public OppositionReport getOppositionReport() { - return this.oppositionReport; - } + // ---------------------------------------------------------------------------------- + // JPA-mappings of other tables referencing to this table (final_seminar_opposition) + // ---------------------------------------------------------------------------------- + @OneToOne(optional = true, orphanRemoval = true, cascade = CascadeType.ALL, + mappedBy = "finalSeminarOpposition") + private OppositionReport oppositionReport; + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public Integer getPoints() { return this.points; } - public String getFeedback() { - return this.feedback; - } - - public void setOpponentReport(FileReference opponentReport) { - this.opponentReport = opponentReport; - } - - public void setOppositionReport(OppositionReport oppositionReport) { - this.oppositionReport = oppositionReport; - } - public void setPoints(Integer points) { this.points = points; } + public String getFeedback() { + return this.feedback; + } + public void setFeedback(String feedback) { this.feedback = feedback; } + public FileReference getOpponentReport() { + return this.opponentReport; + } + + public void setOpponentReport(FileReference opponentReport) { + this.opponentReport = opponentReport; + } + + public Project getProject() { + return this.project; + } + + public void setProject(final Project project) { + this.project = project; + } + + public OppositionReport getOppositionReport() { + return this.oppositionReport; + } + + public void setOppositionReport(OppositionReport oppositionReport) { + this.oppositionReport = oppositionReport; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -90,13 +107,20 @@ public class FinalSeminarOpposition extends FinalSeminarParticipation { && Objects.equals(this.getProject(), other.getProject()); } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), this.getProject()); + } + + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- @Override protected boolean canEqual(final Object other) { return other instanceof FinalSeminarOpposition; } - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), this.getProject()); + public ProjectType getProjectType() { + return getFinalSeminar().getProject().getProjectType(); } } diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarParticipation.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarParticipation.java index 43d94e05e8..8d97c21020 100644 --- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarParticipation.java +++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarParticipation.java @@ -1,64 +1,66 @@ package se.su.dsv.scipro.finalseminar; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.MappedSuperclass; import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.util.Objects; @MappedSuperclass public abstract class FinalSeminarParticipation extends DomainObject { - + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(optional = false) - private User user; + @Basic + @Enumerated(EnumType.STRING) + @Column(name = "grade") + private FinalSeminarGrade grade = null; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in tables whose entity class inherits from + // FinalSeminarParticipation class (such as final_seminar_active_participation, + // final_seminar_opposition, final_seminar_respondent) referencing other tables. + // ---------------------------------------------------------------------------------- @ManyToOne(optional = false) + @JoinColumn(name = "final_seminar_id", referencedColumnName = "id") private FinalSeminar finalSeminar; - @Enumerated(EnumType.STRING) - private FinalSeminarGrade grade = null; + @ManyToOne(optional = false) + @JoinColumn(name = "user_id", referencedColumnName = "id") + private User user; + + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- + protected FinalSeminarParticipation() { + } protected FinalSeminarParticipation(User user, FinalSeminar finalSeminar) { this.user = user; this.finalSeminar = finalSeminar; } - protected FinalSeminarParticipation() { - } - - public boolean isApproved() { - return grade == FinalSeminarGrade.APPROVED; - } - - public boolean hasGrade() { - return (grade != null); - } - - public void setUser(final User user) { - this.user = user; - } - - public void setFinalSeminar(final FinalSeminar finalSeminar) { - this.finalSeminar = finalSeminar; - } - + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- @Override public Long getId() { return this.id; } - public User getUser() { - return this.user; - } - - public FinalSeminar getFinalSeminar() { - return this.finalSeminar; - } - public FinalSeminarGrade getGrade() { return this.grade; } @@ -67,6 +69,29 @@ public abstract class FinalSeminarParticipation extends DomainObject { this.grade = grade; } + public boolean hasGrade() { + return (grade != null); + } + + public FinalSeminar getFinalSeminar() { + return this.finalSeminar; + } + + public void setFinalSeminar(final FinalSeminar finalSeminar) { + this.finalSeminar = finalSeminar; + } + + public User getUser() { + return this.user; + } + + public void setUser(final User user) { + this.user = user; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -77,12 +102,20 @@ public abstract class FinalSeminarParticipation extends DomainObject { && Objects.equals(this.getFinalSeminar(), other.getFinalSeminar()); } - protected boolean canEqual(final Object other) { - return other instanceof FinalSeminarParticipation; - } - @Override public int hashCode() { return Objects.hash(this.getUser(), this.getFinalSeminar()); } + + // ---------------------------------------------------------------------------------- + // Other methods + // ---------------------------------------------------------------------------------- + + protected boolean canEqual(final Object other) { + return other instanceof FinalSeminarParticipation; + } + + public boolean isApproved() { + return grade == FinalSeminarGrade.APPROVED; + } } diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarRespondent.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarRespondent.java index 2178db68c1..92bf8ee457 100644 --- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarRespondent.java +++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarRespondent.java @@ -8,17 +8,17 @@ import jakarta.persistence.Entity; import jakarta.persistence.Table; @Entity -@Cacheable(true) @Table(name = "final_seminar_respondent") +@Cacheable(true) public class FinalSeminarRespondent extends FinalSeminarParticipation { + protected FinalSeminarRespondent() { + } + public FinalSeminarRespondent(User student, FinalSeminar finalSeminar) { super(student, finalSeminar); } - protected FinalSeminarRespondent() { - } - public Project getProject() { return getFinalSeminar().getProject(); } diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarSettings.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarSettings.java index b95f64e994..7a62ea83e9 100644 --- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarSettings.java +++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarSettings.java @@ -7,6 +7,7 @@ import java.util.Objects; @Entity @Cacheable(true) +@Table(name = "final_seminar_settings") public class FinalSeminarSettings extends DomainObject { public static final int DEFAULT_DAYS_AHEAD_TO_UPLOAD_THESIS = 10; public static final int DEFAULT_DAYS_AHEAD_TO_REGISTER_OPPOSITION = 3; @@ -22,25 +23,26 @@ public class FinalSeminarSettings extends DomainObject { this.id = id; } - @Basic(optional = false) + @Column(name = "days_ahead_to_create", nullable = false) private int daysAheadToCreate; - @Basic(optional = false) + @Column(name = "days_ahead_to_register_participation", nullable = false) private int daysAheadToRegisterParticipation = DEFAULT_DAYS_AHEAD_TO_REGISTER_PARTICIPATION; - @Basic(optional = false) + @Column(name = "days_ahead_to_register_opposition", nullable = false) private int daysAheadToRegisterOpposition = DEFAULT_DAYS_AHEAD_TO_REGISTER_OPPOSITION; - @Basic(optional = false) + @Column(name = "days_ahead_to_upload_thesis", nullable = false) private int daysAheadToUploadThesis = DEFAULT_DAYS_AHEAD_TO_UPLOAD_THESIS; - @Basic(optional = false) + @Column(name = "thesis_must_be_pdf", nullable = false) private boolean thesisMustBePDF = false; - @Basic(optional = true) + @Column(name = "evaluation_url", nullable = true) private String evaluationURL; @Basic(optional = false) + @Column(name = "opposition_priority_days", nullable = false) private int oppositionPriorityDays; public boolean getThesisMustBePDF() { diff --git a/core/src/main/java/se/su/dsv/scipro/finalthesis/FinalThesis.java b/core/src/main/java/se/su/dsv/scipro/finalthesis/FinalThesis.java index 894e798a5f..818bfc2b0c 100644 --- a/core/src/main/java/se/su/dsv/scipro/finalthesis/FinalThesis.java +++ b/core/src/main/java/se/su/dsv/scipro/finalthesis/FinalThesis.java @@ -21,50 +21,67 @@ import jakarta.persistence.Table; import java.time.Instant; import java.time.LocalDate; import java.time.ZoneId; -import java.util.*; +import java.util.Date; +import java.util.Objects; @Entity -@Table +@Table(name = "final_thesis") public class FinalThesis extends DomainObject { - public enum Status { - APPROVED, REJECTED, NO_DECISION - } - + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(optional = false) - @JoinColumn(name = "document_reference_id") - private FileReference document; + @Basic + @Column(name = "title_sv") + private String swedishTitle; - @ManyToOne(optional = true) - @JoinColumn(name = "text_matching_document_reference_id") - private FileReference textMatchingDocument; + @Basic + @Column(name = "title_en") + private String englishTitle; + + @Basic + @Column(name = "status") + @Enumerated(EnumType.STRING) + private Status status = Status.NO_DECISION; + + @Basic + @Column(name = "date_approved") + private Date dateApproved; + + @Basic + @Column(name = "date_rejected") + private Date dateRejected; + + @Basic + @Column(name = "rejection_comment") + private String rejectionComment; @Basic @Column(name = "text_matching_analysis") private String textMatchingAnalysis; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (final_thesis) referencing other tables. + // ---------------------------------------------------------------------------------- + @ManyToOne(optional = true) + @JoinColumn(name = "text_matching_document_reference_id", referencedColumnName = "id") + private FileReference textMatchingDocument; + @ManyToOne(optional = false) - @JoinColumn(name = "project_id") + @JoinColumn(name = "document_reference_id", referencedColumnName = "id") + private FileReference document; + + @ManyToOne(optional = false) + @JoinColumn(name = "project_id", referencedColumnName = "id") private Project project; - @Enumerated(EnumType.STRING) - private Status status = Status.NO_DECISION; - - private Date dateApproved; - - private Date dateRejected; - - private String englishTitle; - - private String swedishTitle; - - @Column(name = "rejection_comment") - private String rejectionComment; - + // ---------------------------------------------------------------------------------- + // JPA lifecycle method + // ---------------------------------------------------------------------------------- @PrePersist @PreUpdate void cleanTitle() { @@ -72,6 +89,126 @@ public class FinalThesis extends DomainObject { this.swedishTitle = clean(this.swedishTitle); } + + + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- + @Override + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getEnglishTitle() { + return this.englishTitle; + } + + public void setEnglishTitle(String englishTitle) { + this.englishTitle = englishTitle; + } + + public String getSwedishTitle() { + return this.swedishTitle; + } + + public void setSwedishTitle(String swedishTitle) { + this.swedishTitle = swedishTitle; + } + + public Status getStatus() { + return this.status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public Date getDateApproved() { + return dateApproved; + } + + public void setDateApproved(Date dateApproved) { + this.dateApproved = dateApproved; + } + + public Date getDateRejected() { + return dateRejected; + } + + public void setDateRejected(Date dateRejected) { + this.dateRejected = dateRejected; + } + + public String getRejectionComment() { + return rejectionComment; + } + + public void setRejectionComment(String rejectionComment) { + this.rejectionComment = rejectionComment; + } + + public String getTextMatchingAnalysis() { + return textMatchingAnalysis; + } + + public void setTextMatchingAnalysis(String textMatchingAnalysis) { + this.textMatchingAnalysis = textMatchingAnalysis; + } + + public FileReference getTextMatchingDocument() { + return this.textMatchingDocument; + } + + public void setTextMatchingDocument(FileReference textMatchingDocument) { + this.textMatchingDocument = textMatchingDocument; + } + + public FileReference getDocument() { + return this.document; + } + + public void setDocument(FileReference fileDescription) { + this.document = fileDescription; + } + + public Project getProject() { + return this.project; + } + + public void setProject(Project project) { + this.project = project; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- + @Override + public boolean equals(final Object o) { + if (o == this) return true; + if (!(o instanceof FinalThesis)) return false; + final FinalThesis other = (FinalThesis) o; + return other.canEqual(this) + && Objects.equals(this.getDocument(), other.getDocument()) + && Objects.equals(this.getProject(), other.getProject()); + } + + @Override + public int hashCode() { + return Objects.hash(this.getDocument(), this.getProject()); + } + + @Override + public String toString() { + return "FinalThesis(id=" + this.getId() + ", fileDescription=" + this.getDocument() + ", textMatchingDocument=" + this.getTextMatchingDocument() + ", project=" + this.getProject() + ", status=" + this.getStatus() + ", dateApproved=" + this.getDateApproved() + ", dateRejected=" + this.getDateRejected() + ", englishTitle=" + this.getEnglishTitle() + ", swedishTitle=" + this.getSwedishTitle() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other methods + // ---------------------------------------------------------------------------------- private String clean(String str) { if (str == null) { return null; @@ -83,125 +220,23 @@ public class FinalThesis extends DomainObject { .trim(); } - @Override - public Long getId() { - return this.id; - } - - public FileReference getDocument() { - return this.document; - } - - public FileReference getTextMatchingDocument() { - return this.textMatchingDocument; - } - - public Project getProject() { - return this.project; - } - - public Status getStatus() { - return this.status; - } - - public String getEnglishTitle() { - return this.englishTitle; - } - - public String getSwedishTitle() { - return this.swedishTitle; - } - - public void setId(Long id) { - this.id = id; - } - - public void setDocument(FileReference fileDescription) { - this.document = fileDescription; - } - - public void setTextMatchingDocument(FileReference textMatchingDocument) { - this.textMatchingDocument = textMatchingDocument; - } - - public void setProject(Project project) { - this.project = project; - } - - public void setStatus(Status status) { - this.status = status; - } - - public void setDateApproved(Date dateApproved) { - this.dateApproved = dateApproved; - } - - public void setDateRejected(Date dateRejected) { - this.dateRejected = dateRejected; - } - - public void setEnglishTitle(String englishTitle) { - this.englishTitle = englishTitle; - } - - public void setSwedishTitle(String swedishTitle) { - this.swedishTitle = swedishTitle; - } - - public String getTextMatchingAnalysis() { - return textMatchingAnalysis; - } - - public void setTextMatchingAnalysis(String textMatchingAnalysis) { - this.textMatchingAnalysis = textMatchingAnalysis; - } - - public String getRejectionComment() { - return rejectionComment; - } - - public void setRejectionComment(String rejectionComment) { - this.rejectionComment = rejectionComment; - } - - @Override - public String toString() { - return "FinalThesis(id=" + this.getId() + ", fileDescription=" + this.getDocument() + ", textMatchingDocument=" + this.getTextMatchingDocument() + ", project=" + this.getProject() + ", status=" + this.getStatus() + ", dateApproved=" + this.getDateApproved() + ", dateRejected=" + this.getDateRejected() + ", englishTitle=" + this.getEnglishTitle() + ", swedishTitle=" + this.getSwedishTitle() + ")"; - } - - @Override - public boolean equals(final Object o) { - if (o == this) return true; - if (!(o instanceof FinalThesis)) return false; - final FinalThesis other = (FinalThesis) o; - return other.canEqual(this) - && Objects.equals(this.getDocument(), other.getDocument()) - && Objects.equals(this.getProject(), other.getProject()); - } - protected boolean canEqual(final Object other) { return other instanceof FinalThesis; } - @Override - public int hashCode() { - return Objects.hash(this.getDocument(), this.getProject()); - } - - public boolean isRejected() { - return getStatus() == Status.REJECTED; - } - - public Date getDateRejected() { - return dateRejected; - } - - public Date getDateApproved() { - return dateApproved; - } - public LocalDate getUploadDate() { Instant instant = document.getFileDescription().getDateCreated().toInstant(); return instant.atZone(ZoneId.systemDefault()).toLocalDate(); } + + public boolean isRejected() { + return getStatus() == Status.REJECTED; + } + + // ---------------------------------------------------------------------------------- + // Nested types + // ---------------------------------------------------------------------------------- + public enum Status { + APPROVED, REJECTED, NO_DECISION + } } diff --git a/core/src/main/java/se/su/dsv/scipro/firstmeeting/ProjectFirstMeeting.java b/core/src/main/java/se/su/dsv/scipro/firstmeeting/ProjectFirstMeeting.java index acfaa134eb..759f63f781 100644 --- a/core/src/main/java/se/su/dsv/scipro/firstmeeting/ProjectFirstMeeting.java +++ b/core/src/main/java/se/su/dsv/scipro/firstmeeting/ProjectFirstMeeting.java @@ -1,37 +1,58 @@ package se.su.dsv.scipro.firstmeeting; import com.querydsl.core.annotations.QueryInit; +import jakarta.persistence.Basic; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; + import se.su.dsv.scipro.activityplan.Activity; import se.su.dsv.scipro.system.DomainObject; -import jakarta.persistence.*; import java.util.Date; @Entity @Table(name = "project_first_meeting") public final class ProjectFirstMeeting extends DomainObject { + // ---------------------------------------------------------------------------------- + // basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @QueryInit("activityPlan.project") - @OneToOne(optional = false, cascade = CascadeType.ALL) - private Activity activity; - @Basic(optional = false) + @Column(name = "room") private String room; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (project_first_meeting) referencing + // other tables. + // ---------------------------------------------------------------------------------- + @OneToOne(optional = false, cascade = CascadeType.ALL) + @JoinColumn(name = "activity_id", referencedColumnName = "id") + @QueryInit("activityPlan.project") + private Activity activity; + + // ---------------------------------------------------------------------------------- + // constructor + // ---------------------------------------------------------------------------------- protected ProjectFirstMeeting() {} + // ---------------------------------------------------------------------------------- + // getters and setters + // ---------------------------------------------------------------------------------- @Override public Long getId() { return id; } - public Date getDate() { - return activity.getDate(); - } - public String getRoom() { return room; } @@ -40,10 +61,6 @@ public final class ProjectFirstMeeting extends DomainObject { this.room = room; } - public String getDescription() { - return activity.getDescription(); - } - Activity getActivity() { return activity; } @@ -51,4 +68,15 @@ public final class ProjectFirstMeeting extends DomainObject { void setActivity(Activity activity) { this.activity = activity; } + + // ---------------------------------------------------------------------------------- + // other methods + // ---------------------------------------------------------------------------------- + public Date getDate() { + return activity.getDate(); + } + + public String getDescription() { + return activity.getDescription(); + } } diff --git a/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ForumPost.java b/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ForumPost.java index 7740741863..aff80a655f 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ForumPost.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ForumPost.java @@ -1,5 +1,6 @@ package se.su.dsv.scipro.forum.dataobjects; +import jakarta.persistence.Basic; import jakarta.persistence.GenerationType; import se.su.dsv.scipro.file.FileReference; import se.su.dsv.scipro.system.LazyDeletableDomainObject; @@ -15,54 +16,51 @@ import jakarta.persistence.Lob; import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; import jakarta.persistence.Table; -import java.util.*; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; @Entity @Table(name = "forum_post") public class ForumPost extends LazyDeletableDomainObject { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Lob + @Basic @Column(name = "content", nullable = false) + @Lob private String content; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (forum_post) referencing other + // tables. + // ---------------------------------------------------------------------------------- @ManyToOne - @JoinColumn(name = "user", nullable = true) - private User postedBy; - - @ManyToOne - @JoinColumn(name = "thread", nullable = false) + @JoinColumn(name = "thread_id", nullable = false) private ForumThread forumThread; + @ManyToOne + @JoinColumn(name = "user_id", nullable = true) + private User postedBy; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of other tables referencing to this table "forum_post" + // ---------------------------------------------------------------------------------- @OneToMany(orphanRemoval = true) - @JoinTable(name = "forum_post_file_description", - joinColumns = {@JoinColumn(name = "forum_post_id")}, + @JoinTable(name = "forum_post_file_reference", + joinColumns = {@JoinColumn(name = "forum_post_id", referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name = "file_reference_id")}) private Set<FileReference> attachments = new HashSet<>(); - public String getSubject() { - return forumThread.getSubject(); - } - - public Set<FileReference> getAttachments() { - return attachments; - } - - public User getPostedBy() { - return postedBy; - } - - public String getContent() { - return content; - } - - public ForumThread getForumThread() { - return forumThread; - } - + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- @Override public Long getId() { return this.id; @@ -72,27 +70,41 @@ public class ForumPost extends LazyDeletableDomainObject { this.id = id; } + public String getContent() { + return content; + } + public void setContent(String content) { this.content = content; } - public void setPostedBy(User postedBy) { - this.postedBy = postedBy; + public ForumThread getForumThread() { + return forumThread; } public void setForumThread(ForumThread forumThread) { this.forumThread = forumThread; } + public User getPostedBy() { + return postedBy; + } + + public void setPostedBy(User postedBy) { + this.postedBy = postedBy; + } + + public Set<FileReference> getAttachments() { + return attachments; + } + public void setAttachments(Set<FileReference> attachments) { this.attachments = attachments; } - @Override - public String toString() { - return "ForumPost(id=" + this.getId() + ", content=" + this.getContent() + ", postedBy=" + this.getPostedBy() + ", forumThread=" + this.getForumThread() + ", attachments=" + this.getAttachments() + ")"; - } - + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -106,10 +118,6 @@ public class ForumPost extends LazyDeletableDomainObject { && Objects.equals(this.getAttachments(), other.getAttachments()); } - protected boolean canEqual(final Object other) { - return other instanceof ForumPost; - } - @Override public int hashCode() { return Objects.hash( @@ -119,4 +127,22 @@ public class ForumPost extends LazyDeletableDomainObject { this.getForumThread(), this.getAttachments()); } + + @Override + public String toString() { + return "ForumPost(id=" + this.getId() + ", content=" + this.getContent() + + ", postedBy=" + this.getPostedBy() + ", forumThread=" + this.getForumThread() + + ", attachments=" + this.getAttachments() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof ForumPost; + } + + public String getSubject() { + return forumThread.getSubject(); + } } diff --git a/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ForumPostReadState.java b/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ForumPostReadState.java index 655a3baf41..eff11f8578 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ForumPostReadState.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ForumPostReadState.java @@ -1,14 +1,21 @@ package se.su.dsv.scipro.forum.dataobjects; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.EmbeddedId; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.io.Serializable; @Entity -@Table(name = "forum_post_read") +@Table(name = "forum_post_read_state") public class ForumPostReadState implements Serializable { + // ---------------------------------------------------------------------------------- + // Basic and embedded JPA-mappings + // ---------------------------------------------------------------------------------- @EmbeddedId private ForumPostReadStateId id; @@ -16,6 +23,9 @@ public class ForumPostReadState implements Serializable { @Column(name = "`read`", nullable = false) private boolean read = false; + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- public ForumPostReadState() { } @@ -23,6 +33,9 @@ public class ForumPostReadState implements Serializable { id = new ForumPostReadStateId(user, post); } + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public ForumPostReadStateId getId() { return id; } @@ -39,4 +52,3 @@ public class ForumPostReadState implements Serializable { this.read = read; } } - diff --git a/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ForumPostReadStateId.java b/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ForumPostReadStateId.java index c596d98513..818fd9ca86 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ForumPostReadStateId.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ForumPostReadStateId.java @@ -11,11 +11,11 @@ import java.util.Objects; @Embeddable public class ForumPostReadStateId implements Serializable { @ManyToOne - @JoinColumn(name = "user", nullable = false) + @JoinColumn(name = "user_id", nullable = false) private User user; @ManyToOne - @JoinColumn(name = "post", nullable = false) + @JoinColumn(name = "forum_post_id", nullable = false) private ForumPost post; public ForumPostReadStateId() { diff --git a/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ForumThread.java b/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ForumThread.java index 3068a8fa62..aaeaf4849e 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ForumThread.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ForumThread.java @@ -1,9 +1,21 @@ package se.su.dsv.scipro.forum.dataobjects; +import jakarta.persistence.Basic; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.OneToMany; +import jakarta.persistence.PostLoad; +import jakarta.persistence.Table; import se.su.dsv.scipro.system.LazyDeletableDomainObject; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -13,17 +25,88 @@ import java.util.Objects; @Inheritance(strategy = InheritanceType.JOINED) public class ForumThread extends LazyDeletableDomainObject { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToMany(mappedBy = "forumThread", cascade = CascadeType.ALL, fetch = FetchType.EAGER) - private List<ForumPost> posts = new ArrayList<>(); - @Basic @Column(name = "subject", nullable = false) private String subject; + // ---------------------------------------------------------------------------------- + // JPA-mappings of other tables referencing to this table "thread" + // ---------------------------------------------------------------------------------- + @OneToMany(mappedBy = "forumThread", cascade = CascadeType.ALL, fetch = FetchType.EAGER) + private List<ForumPost> posts = new ArrayList<>(); + + // ---------------------------------------------------------------------------------- + // JPA-lifecycle method + // ---------------------------------------------------------------------------------- + @PostLoad + void lazyDeletion() { + posts.removeIf(LazyDeletableDomainObject::isDeleted); + } + + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- + @Override + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getSubject() { + return subject; + } + + public void setSubject(String subject) { + this.subject = subject; + } + + public List<ForumPost> getPosts() { + return this.posts; + } + + public void setPosts(List<ForumPost> posts) { + this.posts = posts; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- + @Override + public boolean equals(final Object o) { + if (o == this) return true; + if (!(o instanceof ForumThread)) return false; + final ForumThread other = (ForumThread) o; + return other.canEqual(this) + && Objects.equals(this.getId(), other.getId()); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.getId()); + } + + @Override + public String toString() { + return "ForumThread(id=" + this.getId() + ", subject=" + this.getSubject() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof ForumThread; + } + public void addPost(ForumPost post) { posts.add(post); } @@ -32,15 +115,6 @@ public class ForumThread extends LazyDeletableDomainObject { return posts.size(); } - @PostLoad - void lazyDeletion() { - posts.removeIf(LazyDeletableDomainObject::isDeleted); - } - - public String getSubject() { - return subject; - } - public User getCreatedBy(){ return getPosts().get(0).getPostedBy(); } @@ -53,48 +127,4 @@ public class ForumThread extends LazyDeletableDomainObject { } return false; } - - @Override - public Long getId() { - return this.id; - } - - public List<ForumPost> getPosts() { - return this.posts; - } - - public void setId(Long id) { - this.id = id; - } - - public void setPosts(List<ForumPost> posts) { - this.posts = posts; - } - - public void setSubject(String subject) { - this.subject = subject; - } - - @Override - public boolean equals(final Object o) { - if (o == this) return true; - if (!(o instanceof ForumThread)) return false; - final ForumThread other = (ForumThread) o; - return other.canEqual(this) - && Objects.equals(this.getId(), other.getId()); - } - - protected boolean canEqual(final Object other) { - return other instanceof ForumThread; - } - - @Override - public int hashCode() { - return Objects.hashCode(this.getId()); - } - - @Override - public String toString() { - return "ForumThread(id=" + this.getId() + ", subject=" + this.getSubject() + ")"; - } } diff --git a/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/GroupThread.java b/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/GroupThread.java index 5956a4d6de..ed7d45f410 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/GroupThread.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/GroupThread.java @@ -1,49 +1,70 @@ package se.su.dsv.scipro.forum.dataobjects; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; import se.su.dsv.scipro.group.Group; -import jakarta.persistence.*; import java.io.Serializable; import java.util.Objects; @Entity -@Table(name = "group_thread") +@Table(name = "project_group_thread") public class GroupThread implements Serializable { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (project_group_thread) referencing other + // tables. + // ---------------------------------------------------------------------------------- @ManyToOne - @JoinColumn(name = "group_id", nullable = false) + @JoinColumn(name = "project_group_id", referencedColumnName = "id", nullable = false) private Group group; @OneToOne(cascade = CascadeType.ALL, optional = false) - @JoinColumn(name = "thread_id") + @JoinColumn(name = "thread_id", referencedColumnName = "id") private ForumThread forumThread; + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public Long getId() { return id; } - public Group getGroup() { - return group; - } - - public ForumThread getForumThread() { - return forumThread; - } - public void setId(Long id) { this.id = id; } + public Group getGroup() { + return group; + } + public void setGroup(Group group) { this.group = group; } + public ForumThread getForumThread() { + return forumThread; + } + public void setForumThread(ForumThread forumThread) { this.forumThread = forumThread; } + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -55,10 +76,6 @@ public class GroupThread implements Serializable { && Objects.equals(this.getForumThread(), other.getForumThread()); } - protected boolean canEqual(final Object other) { - return other instanceof GroupThread; - } - @Override public int hashCode() { return Objects.hash(this.getId(), this.getGroup(), this.getForumThread()); @@ -66,6 +83,14 @@ public class GroupThread implements Serializable { @Override public String toString() { - return "GroupThread(id=" + this.getId() + ", group=" + this.getGroup() + ", forumThread=" + this.getForumThread() + ")"; + return "GroupThread(id=" + this.getId() + ", group=" + this.getGroup() + ", forumThread=" + + this.getForumThread() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof GroupThread; } } diff --git a/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ProjectThread.java b/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ProjectThread.java index 32b99a8a84..ba32a9f14f 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ProjectThread.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ProjectThread.java @@ -1,50 +1,70 @@ package se.su.dsv.scipro.forum.dataobjects; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; import se.su.dsv.scipro.project.Project; -import jakarta.persistence.*; import java.io.Serializable; import java.util.Objects; @Entity @Table(name = "project_thread") public class ProjectThread implements Serializable { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToOne(optional = false) - @JoinColumn(name = "thread_id") - private ForumThread forumThread; - + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (project_thread) referencing other + // tables. + // ---------------------------------------------------------------------------------- @ManyToOne(optional = false) - @JoinColumn(name = "project_id") + @JoinColumn(name = "project_id", referencedColumnName = "id") private Project project; + @OneToOne(optional = false) + @JoinColumn(name = "thread_id", referencedColumnName = "id") + private ForumThread forumThread; + + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public Long getId() { return id; } - public Project getProject() { - return project; - } - - public ForumThread getForumThread() { - return forumThread; - } - public void setId(Long id) { this.id = id; } - public void setForumThread(ForumThread forumThread) { - this.forumThread = forumThread; + public Project getProject() { + return project; } public void setProject(Project project) { this.project = project; } + public ForumThread getForumThread() { + return forumThread; + } + + public void setForumThread(ForumThread forumThread) { + this.forumThread = forumThread; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -56,10 +76,6 @@ public class ProjectThread implements Serializable { && Objects.equals(this.getProject(), other.getProject()); } - protected boolean canEqual(final Object other) { - return other instanceof ProjectThread; - } - @Override public int hashCode() { return Objects.hash(this.getId(), this.getForumThread(), this.getProject()); @@ -67,6 +83,14 @@ public class ProjectThread implements Serializable { @Override public String toString() { - return "ProjectThread(id=" + this.getId() + ", forumThread=" + this.getForumThread() + ", project=" + this.getProject() + ")"; + return "ProjectThread(id=" + this.getId() + ", forumThread=" + this.getForumThread() + + ", project=" + this.getProject() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof ProjectThread; } } diff --git a/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ReviewerThread.java b/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ReviewerThread.java index 010a5686d6..5cce25c1ca 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ReviewerThread.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/dataobjects/ReviewerThread.java @@ -1,50 +1,69 @@ package se.su.dsv.scipro.forum.dataobjects; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; import se.su.dsv.scipro.project.Project; -import jakarta.persistence.*; import java.util.Objects; @Entity @Table(name = "reviewer_thread") public class ReviewerThread { + // ---------------------------------------------------------------------------------- + // Basic JPA-mapping + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToOne(optional = false) - @JoinColumn(name = "thread_id") - private ForumThread forumThread; - + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (mail_event) referencing other + // tables. + // ---------------------------------------------------------------------------------- @OneToOne - @JoinColumn(name = "project_id", unique = true) + @JoinColumn(name = "project_id", referencedColumnName = "id", unique = true) private Project project; + @OneToOne(optional = false) + @JoinColumn(name = "thread_id", referencedColumnName = "id") + private ForumThread forumThread; + + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public Long getId() { return this.id; } - public ForumThread getForumThread() { - return this.forumThread; - } - - public Project getProject() { - return this.project; - } - public void setId(Long id) { this.id = id; } - public void setForumThread(ForumThread forumThread) { - this.forumThread = forumThread; + public Project getProject() { + return this.project; } public void setProject(Project project) { this.project = project; } + public ForumThread getForumThread() { + return this.forumThread; + } + + public void setForumThread(ForumThread forumThread) { + this.forumThread = forumThread; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -56,10 +75,6 @@ public class ReviewerThread { && Objects.equals(this.getProject(), other.getProject()); } - protected boolean canEqual(final Object other) { - return other instanceof ReviewerThread; - } - @Override public int hashCode() { return Objects.hash(this.getId(), this.getForumThread(), this.getProject()); @@ -67,6 +82,14 @@ public class ReviewerThread { @Override public String toString() { - return "ReviewerThread(id=" + this.getId() + ", forumThread=" + this.getForumThread() + ", project=" + this.getProject() + ")"; + return "ReviewerThread(id=" + this.getId() + ", forumThread=" + this.getForumThread() + + ", project=" + this.getProject() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof ReviewerThread; } } diff --git a/core/src/main/java/se/su/dsv/scipro/forum/notifications/ForumNotification.java b/core/src/main/java/se/su/dsv/scipro/forum/notifications/ForumNotification.java index 3bc39f38ab..fe2bc877e4 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/notifications/ForumNotification.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/notifications/ForumNotification.java @@ -1,26 +1,44 @@ package se.su.dsv.scipro.forum.notifications; +import jakarta.persistence.Embeddable; +import jakarta.persistence.EmbeddedId; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.MapsId; +import jakarta.persistence.Table; import se.su.dsv.scipro.forum.dataobjects.ForumPost; import se.su.dsv.scipro.notifications.dataobject.NotificationEvent; -import jakarta.persistence.*; import java.io.Serializable; import java.util.Objects; @Entity @Table(name = "forum_notification") class ForumNotification { + // ---------------------------------------------------------------------------------- + // Embedded JPA-mapping + // ---------------------------------------------------------------------------------- @EmbeddedId private Id id = new Id(); + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (forum_notification) referencing other + // tables. + // ---------------------------------------------------------------------------------- @ManyToOne(optional = false) + @JoinColumn(name = "forum_post_id", referencedColumnName = "id") @MapsId("forumPostId") private ForumPost forumPost; @ManyToOne(optional = false) + @JoinColumn(name = "notification_data_id") @MapsId("notificationEventId") private NotificationEvent notificationEvent; + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- protected ForumNotification() { } // JPA ForumNotification(final ForumPost forumPost, final NotificationEvent notificationEvent) { @@ -28,6 +46,9 @@ class ForumNotification { this.notificationEvent = notificationEvent; } + // ---------------------------------------------------------------------------------- + // Properties (Getters) + // ---------------------------------------------------------------------------------- public ForumPost getForumPost() { return forumPost; } @@ -36,6 +57,9 @@ class ForumNotification { return notificationEvent; } + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -47,10 +71,6 @@ class ForumNotification { && Objects.equals(this.getNotificationEvent(), other.getNotificationEvent()); } - protected boolean canEqual(final Object other) { - return other instanceof ForumNotification; - } - @Override public int hashCode() { return Objects.hash(this.id, this.getForumPost(), this.getNotificationEvent()); @@ -58,9 +78,20 @@ class ForumNotification { @Override public String toString() { - return "ForumNotification(id=" + this.id + ", forumPost=" + this.getForumPost() + ", notificationEvent=" + this.getNotificationEvent() + ")"; + return "ForumNotification(id=" + this.id + ", forumPost=" + this.getForumPost() + + ", notificationEvent=" + this.getNotificationEvent() + ")"; } + // ---------------------------------------------------------------------------------- + // Other method + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof ForumNotification; + } + + // ---------------------------------------------------------------------------------- + // Nested type + // ---------------------------------------------------------------------------------- @Embeddable static class Id implements Serializable { private Long forumPostId; @@ -103,7 +134,8 @@ class ForumNotification { @Override public String toString() { - return "ForumNotification.Id(forumPostId=" + this.getForumPostId() + ", notificationEventId=" + this.getNotificationEventId() + ")"; + return "ForumNotification.Id(forumPostId=" + this.getForumPostId() + ", notificationEventId=" + + this.getNotificationEventId() + ")"; } } } diff --git a/core/src/main/java/se/su/dsv/scipro/generalsystemsettings/GeneralSystemSettings.java b/core/src/main/java/se/su/dsv/scipro/generalsystemsettings/GeneralSystemSettings.java index b7f7bc0b0b..511fd841b4 100755 --- a/core/src/main/java/se/su/dsv/scipro/generalsystemsettings/GeneralSystemSettings.java +++ b/core/src/main/java/se/su/dsv/scipro/generalsystemsettings/GeneralSystemSettings.java @@ -14,81 +14,86 @@ public class GeneralSystemSettings extends DomainObject { @Id private Long id = null; - @Basic + @Column(name = "daisy_profile_link_base_url") private String daisyProfileLinkBaseURL; - @Basic + @Column(name = "daisy_select_research_area_url") private String daisySelectResearchAreaURL; @ElementCollection - @CollectionTable(name = "general_system_settings_alarm_recipients") + @CollectionTable(name = "general_system_settings_alarm_recipient", + joinColumns = @JoinColumn(name = "general_system_settings_id", referencedColumnName = "id")) @Column(name = "mail") private List<String> alarmMails = new ArrayList<>(); @ElementCollection - @CollectionTable(name = "general_system_settings_supervisor_change_recipients") + @CollectionTable(name = "general_system_settings_supervisor_change_recipient", + joinColumns = @JoinColumn(name = "general_system_settings_id", referencedColumnName = "id")) @Column(name = "mail") private List<String> supervisorChangeMails = new ArrayList<>(); - @Basic(optional = true) + @Column(name = "project_partner_days_to_live", nullable = true) private int projectPartnerDaysToLive; - @Basic(optional = false) + @Column(name = "mail_notifications", nullable = false) private boolean mailNotifications = true; - @Basic(optional = false) + @Column(name = "mail_from_name", nullable = false) private String mailFromName = "SciPro"; - @Basic(optional = false) + @Column(name = "system_from_mail", nullable = false) private String systemFromMail = "noreply-scipro@dsv.su.se"; - @Basic(optional = false) + @Column(name = "smtp_server", nullable = false) private String smtpServer = "localhost"; + @Column(name = "peer_display_latest_reviews") private boolean peerDisplayLatestReviews = true; - @Basic(optional = false) + @Column(name = "number_of_latest_reviews_displayed", nullable = false) private int numberOfLatestReviewsDisplayed = DEFAULT_NUMER_OF_LATEST_REVIEWS_DISPLAYED; - @Basic(optional = false) + @Column(name = "public_reviews_activated", nullable = false) private boolean publicReviewsActivated = true; - @Basic(optional = false) + @Column(name = "peer_download_enabled", nullable = false) private boolean peerDownloadEnabled = true; - @Basic(optional = false) + @Column(name = "scipro_url", nullable = false) private String sciproURL = "http://localhost:8080/"; - @Basic(optional = false) + @Column(name = "show_single_sign_on", nullable = false) private boolean showSingleSignOn = true; @ElementCollection @Enumerated(EnumType.STRING) - @JoinTable(name = "general_system_settings_system_modules") + @CollectionTable(name = "general_system_settings_system_module", + joinColumns = @JoinColumn(name = "general_system_settings_id", referencedColumnName = "id")) + @Column(name = "system_module") private Set<SystemModule> systemModules = EnumSet.allOf(SystemModule.class); - @Basic(optional = true) + @Column(name = "match_responsible_mail", nullable = true) private String matchResponsibleMail = ""; - @Basic(optional = true) + @Column(name = "reviewer_support_mail", nullable = true) private String reviewerSupportMail; - @Basic(optional = true) + @Column(name = "thesis_support_mail", nullable = true) private String thesisSupportMail; - @Basic(optional = true) + @Column(name = "external_room_booking_url", nullable = true) private String externalRoomBookingURL; - @Basic(optional = true) + @Column(name = "external_getting_started_with_idea_url", nullable = true) private String externalGettingStartedWithIdeaURL; - @Basic(optional = true) + @Column(name = "external_grading_url", nullable = true) private String externalGradingURL; - @Basic(optional = false) + @Column(name = "final_survey_available", nullable = false) private boolean finalSurveyAvailable = false; - @Basic + @Column(name = "active_project_idea_support_mail") private String activeProjectIdeaSupportMail; public GeneralSystemSettings() { diff --git a/core/src/main/java/se/su/dsv/scipro/grading/ApprovedEvent.java b/core/src/main/java/se/su/dsv/scipro/grading/ApprovedEvent.java index dfe7e5b08b..88160eb8a9 100644 --- a/core/src/main/java/se/su/dsv/scipro/grading/ApprovedEvent.java +++ b/core/src/main/java/se/su/dsv/scipro/grading/ApprovedEvent.java @@ -16,20 +16,31 @@ import java.time.Instant; import java.util.Objects; @Entity -@Table(name = "grading_history_approvals") +@Table(name = "grading_history_approval") public class ApprovedEvent { + + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne - @JoinColumn(name = "project_id") - private Project project; - @Temporal(TemporalType.TIMESTAMP) @Column(name = "`when`") private Instant when; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (grading_history_rejections) referencing + // other tables. + // ---------------------------------------------------------------------------------- + @ManyToOne + @JoinColumn(name = "project_id") + private Project project; + + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public Long getId() { return id; } @@ -38,14 +49,6 @@ public class ApprovedEvent { this.id = id; } - public Project getProject() { - return project; - } - - public void setProject(Project project) { - this.project = project; - } - public Instant getWhen() { return when; } @@ -54,6 +57,17 @@ public class ApprovedEvent { this.when = when; } + public Project getProject() { + return project; + } + + public void setProject(Project project) { + this.project = project; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(Object o) { if (this == o) return true; @@ -70,10 +84,7 @@ public class ApprovedEvent { @Override public String toString() { - return "ApprovedEvent{" + - "id=" + id + - ", project=" + project + - ", when=" + when + - '}'; + return "ApprovedEvent{" + "id=" + id + ", project=" + project + + ", when=" + when + '}'; } } diff --git a/core/src/main/java/se/su/dsv/scipro/grading/NationalSubjectCategory.java b/core/src/main/java/se/su/dsv/scipro/grading/NationalSubjectCategory.java index 26323389d8..c2ec2aa67e 100644 --- a/core/src/main/java/se/su/dsv/scipro/grading/NationalSubjectCategory.java +++ b/core/src/main/java/se/su/dsv/scipro/grading/NationalSubjectCategory.java @@ -12,21 +12,20 @@ import java.util.Objects; @Entity @Table(name = "national_subject_category") public class NationalSubjectCategory { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = jakarta.persistence.GenerationType.IDENTITY) @Column(name = "id") private Long id; @Basic - @Column(name = "external_id") - private Integer externalId; - - @Basic - @Column(name = "swedish_name") + @Column(name = "name_sv") private String swedishName; @Basic - @Column(name = "english_name") + @Column(name = "name_en") private String englishName; @Basic @@ -37,9 +36,19 @@ public class NationalSubjectCategory { @Column(name = "preselected") private boolean preselected; + @Basic + @Column(name = "external_id") + private Integer externalId; + + // ---------------------------------------------------------------------------------- + // Constructor + // ---------------------------------------------------------------------------------- public NationalSubjectCategory() { } + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public Long getId() { return id; } @@ -48,14 +57,6 @@ public class NationalSubjectCategory { this.id = id; } - public Integer getExternalId() { - return externalId; - } - - public void setExternalId(Integer externalId) { - this.externalId = externalId; - } - public String getSwedishName() { return swedishName; } @@ -88,6 +89,17 @@ public class NationalSubjectCategory { this.preselected = preselected; } + public Integer getExternalId() { + return externalId; + } + + public void setExternalId(Integer externalId) { + this.externalId = externalId; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(Object o) { if (this == o) { diff --git a/core/src/main/java/se/su/dsv/scipro/grading/PublicationMetadata.java b/core/src/main/java/se/su/dsv/scipro/grading/PublicationMetadata.java index 87b0a82f6c..2fe7236e6c 100644 --- a/core/src/main/java/se/su/dsv/scipro/grading/PublicationMetadata.java +++ b/core/src/main/java/se/su/dsv/scipro/grading/PublicationMetadata.java @@ -17,34 +17,44 @@ import java.util.Objects; @Entity @Table(name = "publication_metadata") public class PublicationMetadata { - + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToOne(optional = false) - private Project project; - @Basic - @Column(name = "abstract_swedish") + @Column(name = "abstract_sv") private String abstractSwedish; @Basic - @Column(name = "abstract_english") + @Column(name = "abstract_en") private String abstractEnglish; @Basic - @Column(name = "keywords_swedish") + @Column(name = "keywords_sv") private String keywordsSwedish; @Basic - @Column(name = "keywords_english") + @Column(name = "keywords_en") private String keywordsEnglish; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (publication_metadata) referencing + // other tables. + // ---------------------------------------------------------------------------------- @ManyToOne @JoinColumn(name = "national_subject_category_id") private NationalSubjectCategory nationalSubjectCategory;; + @OneToOne(optional = false) + @JoinColumn(name = "project_id") + private Project project; + + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public Long getId() { return id; } @@ -53,14 +63,6 @@ public class PublicationMetadata { this.id = id; } - public Project getProject() { - return project; - } - - public void setProject(Project project) { - this.project = project; - } - public String getAbstractSwedish() { return abstractSwedish; } @@ -101,19 +103,17 @@ public class PublicationMetadata { this.nationalSubjectCategory = nationalSubjectCategory; } - @Override - public String toString() { - return "PublicationMetadata{" + - "id=" + id + - ", project=" + project + - ", abstractSwedish='" + abstractSwedish + '\'' + - ", abstractEnglish='" + abstractEnglish + '\'' + - ", keywordsSwedish='" + keywordsSwedish + '\'' + - ", keywordsEnglish='" + keywordsEnglish + '\'' + - ", nationalSubjectCategory=" + nationalSubjectCategory + '\'' + - '}'; + public Project getProject() { + return project; } + public void setProject(Project project) { + this.project = project; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(Object o) { return o instanceof PublicationMetadata that && @@ -124,4 +124,15 @@ public class PublicationMetadata { public int hashCode() { return Objects.hashCode(id); } + + @Override + public String toString() { + return "PublicationMetadata{" + "id=" + id + ", project=" + project + + ", abstractSwedish='" + abstractSwedish + '\'' + + ", abstractEnglish='" + abstractEnglish + '\'' + + ", keywordsSwedish='" + keywordsSwedish + '\'' + + ", keywordsEnglish='" + keywordsEnglish + '\'' + + ", nationalSubjectCategory=" + nationalSubjectCategory + '\'' + + '}'; + } } diff --git a/core/src/main/java/se/su/dsv/scipro/grading/RejectionEvent.java b/core/src/main/java/se/su/dsv/scipro/grading/RejectionEvent.java index 745eaf14a8..d7a24907e3 100644 --- a/core/src/main/java/se/su/dsv/scipro/grading/RejectionEvent.java +++ b/core/src/main/java/se/su/dsv/scipro/grading/RejectionEvent.java @@ -17,23 +17,35 @@ import java.time.Instant; import java.util.Objects; @Entity -@Table(name = "grading_history_rejections") +@Table(name = "grading_history_rejection") public class RejectionEvent { + + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne - @JoinColumn(name = "project_id") - private Project project; + @Basic + @Column(name = "reason") + private String reason; @Temporal(TemporalType.TIMESTAMP) @Column(name = "`when`") private Instant when; - @Basic - private String reason; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (grading_history_rejections) referencing + // other tables. + // ---------------------------------------------------------------------------------- + @ManyToOne + @JoinColumn(name = "project_id") + private Project project; + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public Long getId() { return id; } @@ -42,22 +54,6 @@ public class RejectionEvent { this.id = id; } - public Project getProject() { - return project; - } - - public void setProject(Project project) { - this.project = project; - } - - public Instant getWhen() { - return when; - } - - public void setWhen(Instant when) { - this.when = when; - } - public String getReason() { return reason; } @@ -66,6 +62,25 @@ public class RejectionEvent { this.reason = reason; } + public Instant getWhen() { + return when; + } + + public void setWhen(Instant when) { + this.when = when; + } + + public Project getProject() { + return project; + } + + public void setProject(Project project) { + this.project = project; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/core/src/main/java/se/su/dsv/scipro/grading/SubmissionEvent.java b/core/src/main/java/se/su/dsv/scipro/grading/SubmissionEvent.java index 664c1e6bcf..fd88070c36 100644 --- a/core/src/main/java/se/su/dsv/scipro/grading/SubmissionEvent.java +++ b/core/src/main/java/se/su/dsv/scipro/grading/SubmissionEvent.java @@ -18,27 +18,38 @@ import java.time.Instant; import java.util.Objects; @Entity -@Table(name = "grading_history_submissions") +@Table(name = "grading_history_submission") public class SubmissionEvent { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne - @JoinColumn(name = "project_id") - private Project project; - - @ManyToOne - @JoinColumn(name = "author_id") - private User author; - @Temporal(TemporalType.TIMESTAMP) @Column(name = "`when`") private Instant when; @Basic + @Column(name = "corrections") private String corrections; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (grading_history_submission) referencing + // other tables. + // ---------------------------------------------------------------------------------- + @ManyToOne + @JoinColumn(name = "project_id", referencedColumnName = "id") + private Project project; + + @ManyToOne + @JoinColumn(name = "author_user_id", referencedColumnName = "id") + private User author; + + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public Long getId() { return id; } @@ -47,22 +58,6 @@ public class SubmissionEvent { this.id = id; } - public Project getProject() { - return project; - } - - public void setProject(Project project) { - this.project = project; - } - - public User getAuthor() { - return author; - } - - public void setAuthor(User user) { - this.author = user; - } - public Instant getWhen() { return when; } @@ -79,6 +74,25 @@ public class SubmissionEvent { this.corrections = corrections; } + public Project getProject() { + return project; + } + + public void setProject(Project project) { + this.project = project; + } + + public User getAuthor() { + return author; + } + + public void setAuthor(User user) { + this.author = user; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(Object o) { if (this == o) return true; @@ -97,11 +111,8 @@ public class SubmissionEvent { @Override public String toString() { - return "RejectionEvent{" + - "id=" + id + - ", project=" + project + - ", author=" + author + - ", when=" + when + + return "RejectionEvent{" + "id=" + id + ", project=" + project + + ", author=" + author + ", when=" + when + ", corrections='" + corrections + '\'' + '}'; } diff --git a/core/src/main/java/se/su/dsv/scipro/group/Group.java b/core/src/main/java/se/su/dsv/scipro/group/Group.java index c85082e740..11aecf59e8 100644 --- a/core/src/main/java/se/su/dsv/scipro/group/Group.java +++ b/core/src/main/java/se/su/dsv/scipro/group/Group.java @@ -18,30 +18,124 @@ public class Group extends DomainObject { public static final int STRING_MAX_LENGTH = 255; + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(length = STRING_MAX_LENGTH) @Basic(optional = false) + @Column(name = "title", length = STRING_MAX_LENGTH) private String title; @Basic(optional = true) + @Column(name = "description") private String description; + @Basic + @Column(name = "active") + private boolean active = true; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (project_group) referencing other tables. + // ---------------------------------------------------------------------------------- //Creator, should be a supervisor @ManyToOne(optional = false) - @JoinColumn(name = "user_id") + @JoinColumn(name = "user_id", referencedColumnName = "id") private User user; + // ---------------------------------------------------------------------------------- + // @ManyToMany JPA-mappings + // ---------------------------------------------------------------------------------- @ManyToMany - @JoinTable( - name = "project_group_project", - joinColumns = @JoinColumn(name = "project_group_id"), - inverseJoinColumns = @JoinColumn(name = "project_id")) + @JoinTable(name = "project_group_project", + joinColumns = @JoinColumn(name = "project_group_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "project_id", referencedColumnName = "id")) private Set<Project> projects = new HashSet<>(); - private boolean active = true; + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- + @Override + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return this.description; + } + + public void setDescription(String description) { + this.description = description; + } + + public boolean isActive() { + return this.active; + } + + public void setActive(boolean active) { + this.active = active; + } + + public User getUser() { + return this.user; + } + + public void setUser(User user) { + this.user = user; + } + + public Set<Project> getProjects() { + return projects; + } + + public void setProjects(Set<Project> projects) { + this.projects = projects; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- + @Override + public boolean equals(final Object o) { + if (o == this) return true; + if (!(o instanceof Group)) return false; + final Group other = (Group) o; + return other.canEqual(this) + && Objects.equals(this.getId(), other.getId()); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.getId()); + } + + @Override + public String toString() { + return "Group(id=" + this.getId() + ", title=" + this.getTitle() + ", description=" + + this.getDescription() + ", user=" + this.getUser() + ", projects=" + + this.getProjects() + ", active=" + this.isActive() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof Group; + } public boolean isAuthor(final User user) { for (Project project : projects) { @@ -58,76 +152,4 @@ public class Group extends DomainObject { .filter(member -> member.getType() != Member.Type.REVIEWER) .toList(); } - - public Set<Project> getProjects() { - return projects; - } - - public String getTitle() { - return title; - } - - @Override - public Long getId() { - return this.id; - } - - public String getDescription() { - return this.description; - } - - public User getUser() { - return this.user; - } - - public boolean isActive() { - return this.active; - } - - public void setId(Long id) { - this.id = id; - } - - public void setTitle(String title) { - this.title = title; - } - - public void setDescription(String description) { - this.description = description; - } - - public void setUser(User user) { - this.user = user; - } - - public void setProjects(Set<Project> projects) { - this.projects = projects; - } - - public void setActive(boolean active) { - this.active = active; - } - - @Override - public String toString() { - return "Group(id=" + this.getId() + ", title=" + this.getTitle() + ", description=" + this.getDescription() + ", user=" + this.getUser() + ", projects=" + this.getProjects() + ", active=" + this.isActive() + ")"; - } - - @Override - public boolean equals(final Object o) { - if (o == this) return true; - if (!(o instanceof Group)) return false; - final Group other = (Group) o; - return other.canEqual(this) - && Objects.equals(this.getId(), other.getId()); - } - - protected boolean canEqual(final Object other) { - return other instanceof Group; - } - - @Override - public int hashCode() { - return Objects.hashCode(this.getId()); - } -} \ No newline at end of file +} diff --git a/core/src/main/java/se/su/dsv/scipro/integration/activityfinalseminar/ActivityFinalSeminar.java b/core/src/main/java/se/su/dsv/scipro/integration/activityfinalseminar/ActivityFinalSeminar.java index f5bd35bd82..7a34082b32 100644 --- a/core/src/main/java/se/su/dsv/scipro/integration/activityfinalseminar/ActivityFinalSeminar.java +++ b/core/src/main/java/se/su/dsv/scipro/integration/activityfinalseminar/ActivityFinalSeminar.java @@ -1,30 +1,49 @@ package se.su.dsv.scipro.integration.activityfinalseminar; +import jakarta.persistence.AttributeOverride; +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import jakarta.persistence.EmbeddedId; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.MapsId; +import jakarta.persistence.Table; + import se.su.dsv.scipro.activityplan.Activity; import se.su.dsv.scipro.finalseminar.FinalSeminar; -import jakarta.persistence.*; import java.io.Serializable; import java.util.Objects; @Entity @Table(name = "activity_final_seminar") class ActivityFinalSeminar { + // ---------------------------------------------------------------------------------- + // embedded JPA-mappings + // ---------------------------------------------------------------------------------- @EmbeddedId @AttributeOverride(name = "activityId", column = @Column(name = "activity_id")) @AttributeOverride(name = "finalSeminarId", column = @Column(name = "final_seminar_id")) private Id id = new Id(); + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (activity_final_seminiar) referencing + // other tables. + // ---------------------------------------------------------------------------------- @ManyToOne @MapsId("activityId") - @JoinColumn(name = "activity_id") + @JoinColumn(name = "activity_id", referencedColumnName = "id") private Activity activity; @ManyToOne @MapsId("finalSeminarId") - @JoinColumn(name = "final_seminar_id") + @JoinColumn(name = "final_seminar_id", referencedColumnName = "id") private FinalSeminar finalSeminar; + // ---------------------------------------------------------------------------------- + // constructor + // ---------------------------------------------------------------------------------- protected ActivityFinalSeminar() { // JPA } @@ -34,6 +53,9 @@ class ActivityFinalSeminar { this.finalSeminar = finalSeminar; } + // ---------------------------------------------------------------------------------- + // getters + // ---------------------------------------------------------------------------------- public Id getId() { return this.id; } @@ -46,6 +68,9 @@ class ActivityFinalSeminar { return this.finalSeminar; } + // ---------------------------------------------------------------------------------- + // other methods + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -57,10 +82,6 @@ class ActivityFinalSeminar { && Objects.equals(this.getFinalSeminar(), other.getFinalSeminar()); } - protected boolean canEqual(final Object other) { - return other instanceof ActivityFinalSeminar; - } - @Override public int hashCode() { return Objects.hash(this.getId(), this.getActivity(), this.getFinalSeminar()); @@ -71,6 +92,13 @@ class ActivityFinalSeminar { return "ActivityFinalSeminar(id=" + this.getId() + ", activity=" + this.getActivity() + ", finalSeminar=" + this.getFinalSeminar() + ")"; } + protected boolean canEqual(final Object other) { + return other instanceof ActivityFinalSeminar; + } + + // ---------------------------------------------------------------------------------- + // nested class + // ---------------------------------------------------------------------------------- @Embeddable static class Id implements Serializable { private Long activityId; diff --git a/core/src/main/java/se/su/dsv/scipro/integration/activityforum/ActivityThread.java b/core/src/main/java/se/su/dsv/scipro/integration/activityforum/ActivityThread.java index 89d7f0ee43..a890466fc5 100644 --- a/core/src/main/java/se/su/dsv/scipro/integration/activityforum/ActivityThread.java +++ b/core/src/main/java/se/su/dsv/scipro/integration/activityforum/ActivityThread.java @@ -1,27 +1,44 @@ package se.su.dsv.scipro.integration.activityforum; +import jakarta.persistence.Embeddable; +import jakarta.persistence.EmbeddedId; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.MapsId; +import jakarta.persistence.Table; + import se.su.dsv.scipro.activityplan.Activity; import se.su.dsv.scipro.forum.dataobjects.ProjectThread; -import jakarta.persistence.*; import java.io.Serializable; import java.util.Objects; @Entity @Table(name = "activity_thread") class ActivityThread { + // ---------------------------------------------------------------------------------- + // basic and embedded JPA-mappings + // ---------------------------------------------------------------------------------- @EmbeddedId private Id id = new Id(); - @ManyToOne - @MapsId("threadId") - @JoinColumn(name = "project_thread_id") - private ProjectThread thread; - + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (activity_thread) referencing other tables. + // ---------------------------------------------------------------------------------- @ManyToOne @MapsId("activityId") + @JoinColumn(name = "activity_id", referencedColumnName = "id") private Activity activity; + @ManyToOne + @MapsId("threadId") + @JoinColumn(name = "project_thread_id", referencedColumnName = "id") + private ProjectThread thread; + + // ---------------------------------------------------------------------------------- + // constructor + // ---------------------------------------------------------------------------------- protected ActivityThread() { // JPA } @@ -31,6 +48,9 @@ class ActivityThread { this.activity = activity; } + // ---------------------------------------------------------------------------------- + // getters and setters + // ---------------------------------------------------------------------------------- public Id getId() { return this.id; } @@ -43,6 +63,9 @@ class ActivityThread { return this.activity; } + // ---------------------------------------------------------------------------------- + // other methods + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -54,10 +77,6 @@ class ActivityThread { && Objects.equals(this.getActivity(), other.getActivity()); } - protected boolean canEqual(final Object other) { - return other instanceof ActivityThread; - } - @Override public int hashCode() { return Objects.hash(this.getId(), this.getThread(), this.getActivity()); @@ -68,6 +87,13 @@ class ActivityThread { return "ActivityThread(id=" + this.getId() + ", thread=" + this.getThread() + ", activity=" + this.getActivity() + ")"; } + protected boolean canEqual(final Object other) { + return other instanceof ActivityThread; + } + + // ---------------------------------------------------------------------------------- + // nested class + // ---------------------------------------------------------------------------------- @Embeddable static class Id implements Serializable { private Long threadId; diff --git a/core/src/main/java/se/su/dsv/scipro/mail/MailEvent.java b/core/src/main/java/se/su/dsv/scipro/mail/MailEvent.java index 200d362663..a8b99efd4d 100755 --- a/core/src/main/java/se/su/dsv/scipro/mail/MailEvent.java +++ b/core/src/main/java/se/su/dsv/scipro/mail/MailEvent.java @@ -1,5 +1,6 @@ package se.su.dsv.scipro.mail; +import jakarta.persistence.CollectionTable; import jakarta.persistence.GenerationType; import se.su.dsv.scipro.file.FileReference; import se.su.dsv.scipro.system.DomainObject; @@ -19,61 +20,80 @@ import jakarta.persistence.Lob; import jakarta.persistence.ManyToMany; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; -import java.util.*; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; @Entity @Table(name = "mail_event") @Cacheable(false) public class MailEvent extends DomainObject { public static final int STRING_MAX_LENGTH = 255; + + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @JoinTable( - name = "mail_event_recipients", - joinColumns = @JoinColumn(name = "mail_event_id"), - inverseJoinColumns = @JoinColumn(name = "recipients_id")) - @ManyToMany(fetch = FetchType.EAGER) - private Set<User> recipients = new HashSet<>(); - - @ElementCollection - private Set<String> nonUserRecipients = new HashSet<>(); - - @Column(length = STRING_MAX_LENGTH) @Basic(optional = false) + @Column(name = "subject", length = STRING_MAX_LENGTH) private String subject; - @Column(length = STRING_MAX_LENGTH) @Basic(optional = true) + @Column(name = "from_name", length = STRING_MAX_LENGTH) private String fromName; - @Column(length = STRING_MAX_LENGTH) @Basic(optional = true) + @Column(name = "from_email", length = STRING_MAX_LENGTH) private String fromEmail; - @Lob @Basic(optional = false) + @Column(name = "message_body") + @Lob private String messageBody; @Basic(optional = false) + @Column(name = "sent") private boolean sent = false; @Basic(optional = true) + @Column(name = "message_id") private String messageID; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (mail_event) referencing other + // tables. + // ---------------------------------------------------------------------------------- @ManyToOne(optional = true) - @JoinColumn(name = "attachment_reference_id") + @JoinColumn(name = "attachment_file_reference_id", referencedColumnName = "id") private FileReference attachment; + // ---------------------------------------------------------------------------------- + // @ManyToMany JPA-mappings + // ---------------------------------------------------------------------------------- + @ManyToMany(fetch = FetchType.EAGER) + @JoinTable(name = "mail_event_recipient", + joinColumns = @JoinColumn(name = "mail_event_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "recipient_id", referencedColumnName = "id")) + private Set<User> recipients = new HashSet<>(); + + @ElementCollection + @CollectionTable(name = "mail_event_non_user_recipient", + joinColumns = @JoinColumn(name = "mail_event_id", referencedColumnName = "id")) + @Column(name = "non_user_recipient") + private Set<String> nonUserRecipients = new HashSet<>(); + + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- public MailEvent() { } - public MailEvent( - final String subject, - final String messageBody, - final User recipient, - final String fromName, + public MailEvent(final String subject, final String messageBody, final User recipient, final String fromName, final String fromEmail) { this.subject = subject; this.messageBody = messageBody; @@ -82,13 +102,8 @@ public class MailEvent extends DomainObject { this.fromEmail = fromEmail; } - public MailEvent( - final String subject, - final String messageBody, - final Collection<User> recipients, - final String fromName, - final String fromEmail - ) { + public MailEvent(final String subject, final String messageBody, final Collection<User> recipients, + final String fromName, final String fromEmail) { this.subject = subject; this.messageBody = messageBody; this.recipients.addAll(recipients); @@ -96,35 +111,124 @@ public class MailEvent extends DomainObject { this.fromEmail = fromEmail; } - public boolean isSent() { - return sent; + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- + @Override + public Long getId() { + return this.id; } - public void markSent(final String messageID) { - this.messageID = messageID; - this.sent = true; + public void setId(Long id) { + this.id = id; } - public Set<User> getRecipients() { - return recipients; - } - - public void setMessageBody(String messageBody) { - this.messageBody = messageBody; + public String getSubject() { + return this.subject; } public void setSubject(String subject) { this.subject = subject; } + public String getFromName() { + return this.fromName; + } + public void setFromName(String fromName) { this.fromName = fromName; } + public String getFromEmail() { + return this.fromEmail; + } + public void setFromEmail(String fromEmail) { this.fromEmail = fromEmail; } + public String getMessageBody() { + return this.messageBody; + } + + public void setMessageBody(String messageBody) { + this.messageBody = messageBody; + } + + public boolean isSent() { + return sent; + } + + public void setSent(boolean sent) { + this.sent = sent; + } + + public String getMessageID() { + return this.messageID; + } + + public void setMessageID(String messageID) { + this.messageID = messageID; + } + + public FileReference getAttachment() { + return this.attachment; + } + + public void setAttachment(FileReference attachment) { + this.attachment = attachment; + } + + public Set<User> getRecipients() { + return recipients; + } + + public void setRecipients(Set<User> recipients) { + this.recipients = recipients; + } + + public Set<String> getNonUserRecipients() { + return this.nonUserRecipients; + } + + public void setNonUserRecipients(Set<String> nonUserRecipients) { + this.nonUserRecipients = nonUserRecipients; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- + @Override + public boolean equals(final Object o) { + if (o == this) return true; + if (!(o instanceof MailEvent)) return false; + final MailEvent other = (MailEvent) o; + return other.canEqual(this) + && Objects.equals(this.getId(), other.getId()); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.getId()); + } + + @Override + public String toString() { + return "MailEvent(id=" + this.getId() + ", recipients=" + this.getRecipients() + + ", nonUserRecipients=" + this.getNonUserRecipients() + ", subject=" + + this.getSubject() + ", fromName=" + this.getFromName() + + ", fromEmail=" + this.getFromEmail() + ", messageBody=" + this.getMessageBody() + + ", sent=" + this.isSent() + ", messageID=" + this.getMessageID() + + ", attachment=" + this.getAttachment() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof MailEvent; + } + public void addRecipients(final Iterable<Recipient> recipients) { for (Recipient recipient : recipients) { recipient.accept(new RecipientVisitor<Boolean>() { @@ -141,83 +245,8 @@ public class MailEvent extends DomainObject { } } - @Override - public Long getId() { - return this.id; - } - - public Set<String> getNonUserRecipients() { - return this.nonUserRecipients; - } - - public String getSubject() { - return this.subject; - } - - public String getFromName() { - return this.fromName; - } - - public String getFromEmail() { - return this.fromEmail; - } - - public String getMessageBody() { - return this.messageBody; - } - - public String getMessageID() { - return this.messageID; - } - - public FileReference getAttachment() { - return this.attachment; - } - - public void setId(Long id) { - this.id = id; - } - - public void setRecipients(Set<User> recipients) { - this.recipients = recipients; - } - - public void setNonUserRecipients(Set<String> nonUserRecipients) { - this.nonUserRecipients = nonUserRecipients; - } - - public void setSent(boolean sent) { - this.sent = sent; - } - - public void setMessageID(String messageID) { + public void markSent(final String messageID) { this.messageID = messageID; - } - - public void setAttachment(FileReference attachment) { - this.attachment = attachment; - } - - @Override - public String toString() { - return "MailEvent(id=" + this.getId() + ", recipients=" + this.getRecipients() + ", nonUserRecipients=" + this.getNonUserRecipients() + ", subject=" + this.getSubject() + ", fromName=" + this.getFromName() + ", fromEmail=" + this.getFromEmail() + ", messageBody=" + this.getMessageBody() + ", sent=" + this.isSent() + ", messageID=" + this.getMessageID() + ", attachment=" + this.getAttachment() + ")"; - } - - @Override - public boolean equals(final Object o) { - if (o == this) return true; - if (!(o instanceof MailEvent)) return false; - final MailEvent other = (MailEvent) o; - return other.canEqual(this) - && Objects.equals(this.getId(), other.getId()); - } - - protected boolean canEqual(final Object other) { - return other instanceof MailEvent; - } - - @Override - public int hashCode() { - return Objects.hashCode(this.getId()); + this.sent = true; } } diff --git a/core/src/main/java/se/su/dsv/scipro/match/ApplicationPeriod.java b/core/src/main/java/se/su/dsv/scipro/match/ApplicationPeriod.java index 6955d28d2d..d3c7a21e50 100755 --- a/core/src/main/java/se/su/dsv/scipro/match/ApplicationPeriod.java +++ b/core/src/main/java/se/su/dsv/scipro/match/ApplicationPeriod.java @@ -1,17 +1,30 @@ package se.su.dsv.scipro.match; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; + import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.ProjectType; -import jakarta.persistence.*; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.util.*; - @Entity @Cacheable(true) -@Table(name="ApplicationPeriod") +@Table(name="application_period") public class ApplicationPeriod extends DomainObject { @Id @@ -23,17 +36,16 @@ public class ApplicationPeriod extends DomainObject { private String name; - @Basic + @Column(name = "start_date") private LocalDate startDate = LocalDate.now(); - @Basic + @Column(name = "end_date") private LocalDate endDate = LocalDate.now(); - @Basic - @Column(name = "courseStartDate") + @Column(name = "course_start_date") private LocalDateTime courseStartDateTime = LocalDate.now().atTime(8, 0); - @Basic + @Column(name = "course_end_date") private LocalDate courseEndDate; @OneToMany(fetch = FetchType.LAZY, mappedBy = "applicationPeriod", cascade=CascadeType.ALL, orphanRemoval=true) diff --git a/core/src/main/java/se/su/dsv/scipro/match/ApplicationPeriodExemption.java b/core/src/main/java/se/su/dsv/scipro/match/ApplicationPeriodExemption.java index 717d71f294..82197dc73d 100644 --- a/core/src/main/java/se/su/dsv/scipro/match/ApplicationPeriodExemption.java +++ b/core/src/main/java/se/su/dsv/scipro/match/ApplicationPeriodExemption.java @@ -1,15 +1,23 @@ package se.su.dsv.scipro.match; -import se.su.dsv.scipro.system.User; - -import jakarta.persistence.*; import java.io.Serializable; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.Objects; +import jakarta.persistence.AttributeOverride; +import jakarta.persistence.Column; +import jakarta.persistence.EmbeddedId; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.MapsId; +import jakarta.persistence.Table; + +import se.su.dsv.scipro.system.User; + @Entity -@Table(name = "applicationperiodexemption") +@Table(name = "application_period_exemption") public class ApplicationPeriodExemption implements Serializable { public enum Type { SUBMIT_STUDENT_IDEA(true), @@ -39,16 +47,19 @@ public class ApplicationPeriodExemption implements Serializable { @MapsId("applicationPeriodId") @ManyToOne(optional = false) - @JoinColumn(name = "applicationPeriodId") + @JoinColumn(name = "application_period_id") private ApplicationPeriod applicationPeriod; + @Column(name = "end_date") private LocalDate endDate; private String comment; @ManyToOne(optional = false) + @JoinColumn(name = "granted_by_id") private User grantedBy; + @Column(name = "granted_on") private LocalDateTime grantedOn; public ApplicationPeriodExemptionId getApplicationperiodexemptionId() { diff --git a/core/src/main/java/se/su/dsv/scipro/match/ApplicationPeriodProjectType.java b/core/src/main/java/se/su/dsv/scipro/match/ApplicationPeriodProjectType.java index 0d9a6f0b91..eac5ccfbc2 100644 --- a/core/src/main/java/se/su/dsv/scipro/match/ApplicationPeriodProjectType.java +++ b/core/src/main/java/se/su/dsv/scipro/match/ApplicationPeriodProjectType.java @@ -1,5 +1,7 @@ package se.su.dsv.scipro.match; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Table; import se.su.dsv.scipro.activityplan.ActivityPlanTemplate; import se.su.dsv.scipro.system.ProjectType; @@ -10,19 +12,23 @@ import jakarta.persistence.MapsId; import java.io.Serializable; @Entity +@Table(name = "application_period_project_type") public class ApplicationPeriodProjectType implements Serializable { @EmbeddedId private ApplicationPeriodProjectTypeId applicationPeriodProjectTypeId = new ApplicationPeriodProjectTypeId(); @MapsId("applicationPeriodId") @ManyToOne + @JoinColumn(name = "application_period_id") private ApplicationPeriod applicationPeriod; @MapsId("projectTypeId") @ManyToOne + @JoinColumn(name = "project_type_id") private ProjectType projectType; @ManyToOne(optional = true) + @JoinColumn(name = "activity_plan_template_id") private ActivityPlanTemplate activityPlanTemplate; protected ApplicationPeriodProjectType() {} diff --git a/core/src/main/java/se/su/dsv/scipro/match/FirstMeeting.java b/core/src/main/java/se/su/dsv/scipro/match/FirstMeeting.java index 2df0e579c7..4367c24d73 100755 --- a/core/src/main/java/se/su/dsv/scipro/match/FirstMeeting.java +++ b/core/src/main/java/se/su/dsv/scipro/match/FirstMeeting.java @@ -1,6 +1,16 @@ package se.su.dsv.scipro.match; -import jakarta.persistence.*; +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; + import java.io.Serializable; import java.util.Date; import java.util.Objects; @@ -9,72 +19,92 @@ import java.util.Objects; @Table(name = "idea_first_meeting") @Cacheable(true) public class FirstMeeting implements Serializable { - public static final int LENGTH = 1024; + private static final int LENGTH = 1024; + + // ---------------------------------------------------------------------------------- + // basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Basic(optional = false) - private Date firstMeetingDate; - - @Column(nullable = false, length = LENGTH) - private String room; - - @Column(nullable = true, length = LENGTH) + @Basic + @Column(name = "description", nullable = true, length = LENGTH) private String description; + @Basic(optional = false) + @Column(name = "first_meeting_date") + private Date firstMeetingDate; + + @Basic + @Column(name = "room", nullable = false, length = LENGTH) + private String room; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (idea_first_meeting) referencing other + // tables. + // ---------------------------------------------------------------------------------- @OneToOne(optional = false) + @JoinColumn(name = "idea_id", referencedColumnName = "id") private Idea idea; - public FirstMeeting() { - - } + // ---------------------------------------------------------------------------------- + // constructors + // ---------------------------------------------------------------------------------- + public FirstMeeting() { } public FirstMeeting(Date firstMeetingDate, Idea idea) { this.firstMeetingDate = firstMeetingDate; this.idea = idea; } + // ---------------------------------------------------------------------------------- + // getters and setters + // ---------------------------------------------------------------------------------- + public Long getId() { return this.id; } - public Date getFirstMeetingDate() { - return this.firstMeetingDate; - } - - public String getRoom() { - return this.room; - } - - public String getDescription() { - return this.description; - } - - public Idea getIdea() { - return this.idea; - } - public void setId(Long id) { this.id = id; } - public void setFirstMeetingDate(Date firstMeetingDate) { - this.firstMeetingDate = firstMeetingDate; - } - - public void setRoom(String room) { - this.room = room; + public String getDescription() { + return this.description; } public void setDescription(String description) { this.description = description; } + public Date getFirstMeetingDate() { + return this.firstMeetingDate; + } + + public void setFirstMeetingDate(Date firstMeetingDate) { + this.firstMeetingDate = firstMeetingDate; + } + + public String getRoom() { + return this.room; + } + + public void setRoom(String room) { + this.room = room; + } + + public Idea getIdea() { + return this.idea; + } + public void setIdea(Idea idea) { this.idea = idea; } + // ---------------------------------------------------------------------------------- + // other methods + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -94,11 +124,13 @@ public class FirstMeeting implements Serializable { @Override public int hashCode() { - return Objects.hash(this.getId(), this.getFirstMeetingDate(), this.getRoom(), this.getDescription(), this.getIdea()); + return Objects.hash(this.getId(), this.getFirstMeetingDate(), this.getRoom(), this.getDescription(), + this.getIdea()); } @Override public String toString() { - return "FirstMeeting(id=" + this.getId() + ", firstMeetingDate=" + this.getFirstMeetingDate() + ", room=" + this.getRoom() + ", description=" + this.getDescription() + ", idea=" + this.getIdea() + ")"; + return "FirstMeeting(id=" + this.getId() + ", firstMeetingDate=" + this.getFirstMeetingDate() + ", room=" + + this.getRoom() + ", description=" + this.getDescription() + ", idea=" + this.getIdea() + ")"; } } diff --git a/core/src/main/java/se/su/dsv/scipro/match/Idea.java b/core/src/main/java/se/su/dsv/scipro/match/Idea.java index 15b457b17b..e2772b539b 100755 --- a/core/src/main/java/se/su/dsv/scipro/match/Idea.java +++ b/core/src/main/java/se/su/dsv/scipro/match/Idea.java @@ -1,103 +1,190 @@ package se.su.dsv.scipro.match; import com.querydsl.core.annotations.QueryInit; +import jakarta.persistence.AttributeOverride; +import jakarta.persistence.AttributeOverrides; +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.CascadeType; +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.OrderBy; +import jakarta.persistence.PostLoad; +import jakarta.persistence.PostPersist; +import jakarta.persistence.PostUpdate; +import jakarta.persistence.PrePersist; +import jakarta.persistence.PreUpdate; +import jakarta.persistence.Table; + import se.su.dsv.scipro.data.dataobjects.Member; import se.su.dsv.scipro.project.Project; -import se.su.dsv.scipro.system.*; +import se.su.dsv.scipro.system.DomainObject; +import se.su.dsv.scipro.system.Language; +import se.su.dsv.scipro.system.ProjectType; +import se.su.dsv.scipro.system.ResearchArea; +import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.time.LocalDate; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; import java.util.stream.Collectors; @Entity @Table(name = "idea") @Cacheable(true) public class Idea extends DomainObject { + private static final int DESCRIPTION_LENGTH = 4000; + private static final int PREREQUISITES_LENGTH = 4000; + private static final int TITLE_LENGTH = 1024; - public static final int DESCRIPTION_LENGTH = 4000; - public static final int PREREQUISITES_LENGTH = 4000; - public static final int TITLE_LENGTH = 1024; + // ---------------------------------------------------------------------------------- + // basic and embedded JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(optional = false) - private ProjectType projectType; - - @Enumerated(EnumType.STRING) - private Type type; - - @ManyToOne(optional = false) - private User creator; - + @Basic @Column(nullable = true, length = DESCRIPTION_LENGTH) private String description; + @Basic @Column(nullable = true, length = PREREQUISITES_LENGTH) private String prerequisites; - @OneToMany(fetch = FetchType.LAZY, mappedBy = "idea", cascade = CascadeType.ALL, orphanRemoval = true) - @QueryInit({"user", "program"}) - private Set<IdeaParticipation> ideaParticipations = new HashSet<>(); - - @ManyToOne(optional = true) - private ApplicationPeriod applicationPeriod; - + @Basic @Column(nullable = false, length = TITLE_LENGTH) private String title; - @ManyToOne(optional = true) - private ResearchArea researchArea; - - @ElementCollection - @CollectionTable(name = "idea_language") - @Column(name = "language") + @Basic @Enumerated(EnumType.STRING) - private Set<Language> languages = EnumSet.noneOf(Language.class); + private Type type; + + @Basic + @Column(name = "published") + private boolean published = true; + + @Enumerated(EnumType.STRING) + @Column(name = "cached_status") + private Status cachedStatus; + + @Basic + @Column(name = "inactive") + private boolean inactive = false; @Embedded @AttributeOverrides({ - @AttributeOverride(name = "practicalHow", column = @Column(insertable = false, updatable = false)), - @AttributeOverride(name = "literature", column = @Column(insertable = false, updatable = false)), - @AttributeOverride(name = "theoryHow", column = @Column(insertable = false, updatable = false)), - @AttributeOverride(name = "why", column = @Column(insertable = false, updatable = false)), - @AttributeOverride(name = "what", column = @Column(insertable = false, updatable = false)) + @AttributeOverride(name = "practicalHow", column = @Column(name = "practical_how", insertable = false, updatable = false)), + @AttributeOverride(name = "theoryHow", column = @Column(name = "theory_how", insertable = false, updatable = false)), + @AttributeOverride(name = "what", column = @Column(name = "what", insertable = false, updatable = false)), + @AttributeOverride(name = "why", column = @Column(name = "why", insertable = false, updatable = false)), + @AttributeOverride(name = "literature", column = @Column(name = "literature", insertable = false, updatable = false)) }) private Watson watson; @Embedded + @AttributeOverrides({ + @AttributeOverride(name = "literature", column = @Column(name = "literature", insertable = false, updatable = false)), + @AttributeOverride(name = "background", column = @Column(name = "background", insertable = false, updatable = false)), + @AttributeOverride(name = "problem", column = @Column(name = "problem", insertable = false, updatable = false)), + @AttributeOverride(name = "method", column = @Column(name = "method", insertable = false, updatable = false)), + @AttributeOverride(name = "interests", column = @Column(name = "interests", insertable = false, updatable = false)) + }) private TholanderBox tholanderBox = new TholanderBox(); - @ManyToMany - private Set<Keyword> keywords = new HashSet<>(); + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (idea) referencing other tables. + // ---------------------------------------------------------------------------------- + @ManyToOne(optional = true) + @JoinColumn(name = "application_period_id", referencedColumnName = "id") + private ApplicationPeriod applicationPeriod; + + @ManyToOne(optional = false) + @JoinColumn(name = "creator_user_id", referencedColumnName = "id") + private User creator; + + @OneToOne(optional = true, cascade = CascadeType.ALL) + @JoinColumn(name = "latest_match_id", referencedColumnName = "id") + @QueryInit({"supervisor.user", "supervisor.unit"}) + private Match match; @OneToOne + @JoinColumn(name = "project_id", referencedColumnName = "id") private Project project; - @OneToOne(mappedBy = "idea", orphanRemoval = true, optional = true) - private FirstMeeting firstMeeting; + @ManyToOne(optional = false) + @JoinColumn(name = "project_type_id", referencedColumnName = "id") + private ProjectType projectType; + @ManyToOne(optional = true) + @JoinColumn(name = "research_area_id", referencedColumnName = "id") + private ResearchArea researchArea; + + // ---------------------------------------------------------------------------------- + // @ManyToMany JPA-mappings + // ---------------------------------------------------------------------------------- + + // many-to-many from table "keyword" through table "idea_keyword" + @ManyToMany + @JoinTable(name="idea_keyword", + joinColumns = @JoinColumn(name = "idea_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "keyword_id", referencedColumnName = "id")) + private Set<Keyword> keywords = new HashSet<>(); + + // ---------------------------------------------------------------------------------- + // JPA-mappings of other tables referencing to this table "idea" + // ---------------------------------------------------------------------------------- + + // from table idea_language + @ElementCollection + @CollectionTable(name = "idea_language", + joinColumns = @JoinColumn(name = "idea_id", referencedColumnName = "id")) + @Column(name = "language") + @Enumerated(EnumType.STRING) + private Set<Language> languages = EnumSet.noneOf(Language.class); + + // from table idea_export + @OneToMany(mappedBy = "idea", cascade = CascadeType.ALL) + private List<IdeaExport> exports = new ArrayList<>(); + + // from table idea_student + @OneToMany(fetch = FetchType.LAZY, mappedBy = "idea", cascade = CascadeType.ALL, orphanRemoval = true) + @QueryInit({"user", "program"}) + private Set<IdeaParticipation> ideaParticipations = new HashSet<>(); + + // from table "idea_match" @OneToMany(fetch = FetchType.LAZY, mappedBy = "idea", cascade = CascadeType.ALL) @OrderBy("dateCreated DESC") private List<Match> matchHistory = new ArrayList<>(); - @OneToOne(optional = true, cascade = CascadeType.ALL) - @QueryInit({"supervisor.user", "supervisor.unit"}) - private Match match; - - @Column(name = "published") - private boolean published = true; - - @OneToMany(mappedBy = "idea", cascade = CascadeType.ALL) - private List<IdeaExport> exports = new ArrayList<>(); - - @Enumerated(EnumType.STRING) - private Status cachedStatus; - - @Basic - private boolean inactive = false; + // from table "idea_first_meeting" + @OneToOne(mappedBy = "idea", orphanRemoval = true, optional = true) + private FirstMeeting firstMeeting; + // ---------------------------------------------------------------------------------- + // methods... + // ---------------------------------------------------------------------------------- public Idea copy(User supervisor) { Idea copy = new Idea(); copy.projectType = this.projectType; @@ -448,7 +535,9 @@ public class Idea extends DomainObject { public String toString() { return "Student idea"; } - }, SUPERVISOR { + }, + + SUPERVISOR { @Override public String toString() { return "Supervisor idea"; @@ -463,18 +552,21 @@ public class Idea extends DomainObject { return "Unmatched"; } }, + MATCHED { @Override public String toString() { return "Matched, no project"; } }, + COMPLETED { @Override public String toString() { return "Matched, has project"; } }, + INACTIVE { @Override public String toString() { diff --git a/core/src/main/java/se/su/dsv/scipro/match/IdeaExport.java b/core/src/main/java/se/su/dsv/scipro/match/IdeaExport.java index 39b00e453a..321ccda22b 100644 --- a/core/src/main/java/se/su/dsv/scipro/match/IdeaExport.java +++ b/core/src/main/java/se/su/dsv/scipro/match/IdeaExport.java @@ -1,8 +1,18 @@ package se.su.dsv.scipro.match; +import jakarta.persistence.Basic; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; + import se.su.dsv.scipro.system.DomainObject; -import jakarta.persistence.*; import java.util.Objects; @Entity @@ -11,56 +21,69 @@ public class IdeaExport extends DomainObject { public enum Result { FAIL, SUCCESS } + // ---------------------------------------------------------------------------------- + // basic and embedded JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Enumerated(EnumType.STRING) - private Result result; - @Basic private String reason; + @Enumerated(EnumType.STRING) + private Result result; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (idea_export) referencing other tables + // ---------------------------------------------------------------------------------- @ManyToOne(optional = false) + @JoinColumn(name = "idea_id", referencedColumnName = "id") private Idea idea; - public boolean wasSuccessful() { - return result == Result.SUCCESS; - } - + // ---------------------------------------------------------------------------------- + // getters and setters + // ---------------------------------------------------------------------------------- @Override public Long getId() { return this.id; } - public Result getResult() { - return this.result; - } - - public String getReason() { - return this.reason; - } - - public Idea getIdea() { - return this.idea; - } - public void setId(Long id) { this.id = id; } - public void setResult(Result result) { - this.result = result; + public String getReason() { + return this.reason; } public void setReason(String reason) { this.reason = reason; } + public Result getResult() { + return this.result; + } + + public void setResult(Result result) { + this.result = result; + } + + public Idea getIdea() { + return this.idea; + } + public void setIdea(Idea idea) { this.idea = idea; } + // ---------------------------------------------------------------------------------- + // other methods + // ---------------------------------------------------------------------------------- + public boolean wasSuccessful() { + return result == Result.SUCCESS; + } + @Override public boolean equals(final Object o) { if (o == this) return true; diff --git a/core/src/main/java/se/su/dsv/scipro/match/IdeaParticipation.java b/core/src/main/java/se/su/dsv/scipro/match/IdeaParticipation.java index 625e38cf8f..7bf357d62f 100755 --- a/core/src/main/java/se/su/dsv/scipro/match/IdeaParticipation.java +++ b/core/src/main/java/se/su/dsv/scipro/match/IdeaParticipation.java @@ -1,83 +1,114 @@ package se.su.dsv.scipro.match; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; import se.su.dsv.scipro.system.Program; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.io.Serializable; import java.util.Date; import java.util.Objects; @Entity @Table(name = "idea_student") -@AssociationOverrides({ - @AssociationOverride(name = "idea", - joinColumns = @JoinColumn(name = "idea_id")) }) public class IdeaParticipation implements Serializable { - protected IdeaParticipation() { - - } - - public IdeaParticipation(User student, Idea idea) { - this.user = student; - this.idea = idea; - } + // ---------------------------------------------------------------------------------- + // basic and embedded JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne - private User user; - - @ManyToOne - private Idea idea; - + @Basic + @Column(name = "date_created") private Date dateCreated = new Date(); + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (idea_student) referencing other tables. + // ---------------------------------------------------------------------------------- + @ManyToOne + @JoinColumn(name = "idea_id", referencedColumnName = "id") + private Idea idea; + @ManyToOne(optional = true) + @JoinColumn(name = "program_id", referencedColumnName = "id") private Program program; + @ManyToOne + @JoinColumn(name = "user_id", referencedColumnName = "id") + private User user; + + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- + + // JPA/Hibernate works by create a child class of your entity class with all database + // tricks in it, it therefore requires no-arg constructor to be able to instantiate + // a new instance. + // By creating a protected constructor, JPA/Hibernate still works as expected, but it + // declares the intention that parameters need to be provided when new instances are + // created. + protected IdeaParticipation() { } + + public IdeaParticipation(User student, Idea idea) { + this.user = student; + this.idea = idea; + } + + // ---------------------------------------------------------------------------- + // getters and setters + // ---------------------------------------------------------------------------- public Long getId() { return this.id; } - public User getUser() { - return this.user; - } - - public Idea getIdea() { - return this.idea; - } - - public Date getDateCreated() { - return this.dateCreated; - } - - public Program getProgram() { - return this.program; - } - public void setId(Long id) { this.id = id; } - public void setUser(User user) { - this.user = user; - } - - public void setIdea(Idea idea) { - this.idea = idea; + public Date getDateCreated() { + return this.dateCreated; } public void setDateCreated(Date dateCreated) { this.dateCreated = dateCreated; } + public Idea getIdea() { + return this.idea; + } + + public void setIdea(Idea idea) { + this.idea = idea; + } + + public Program getProgram() { + return this.program; + } + public void setProgram(Program program) { this.program = program; } + public User getUser() { + return this.user; + } + + public void setUser(User user) { + this.user = user; + } + + // ---------------------------------------------------------------------------- + // methods + // ---------------------------------------------------------------------------- @Override public String toString() { return "IdeaParticipation(id=" + this.getId() + ", user=" + this.getUser() + ", idea=" + this.getIdea() + ", dateCreated=" + this.getDateCreated() + ", program=" + this.getProgram() + ")"; diff --git a/core/src/main/java/se/su/dsv/scipro/match/Keyword.java b/core/src/main/java/se/su/dsv/scipro/match/Keyword.java index 320c278981..060efc46b7 100755 --- a/core/src/main/java/se/su/dsv/scipro/match/Keyword.java +++ b/core/src/main/java/se/su/dsv/scipro/match/Keyword.java @@ -1,15 +1,25 @@ package se.su.dsv.scipro.match; +import jakarta.persistence.Cacheable; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.Table; + import se.su.dsv.scipro.system.LazyDeletableDomainObject; import se.su.dsv.scipro.system.ResearchArea; -import jakarta.persistence.*; - import java.util.HashSet; import java.util.Objects; import java.util.Set; @Entity +@Table(name = "keyword") @Cacheable(true) public class Keyword extends LazyDeletableDomainObject { @@ -19,8 +29,10 @@ public class Keyword extends LazyDeletableDomainObject { private String keyword; - @ManyToMany(fetch = FetchType.EAGER,targetEntity=ResearchArea.class) - @JoinTable(name="Keyword_researcharea") + @ManyToMany(fetch = FetchType.EAGER, targetEntity = ResearchArea.class) + @JoinTable(name="keyword_research_area", + joinColumns = @JoinColumn(name = "keyword_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "research_area_id", referencedColumnName = "id")) private Set<ResearchArea> researchAreas = new HashSet<>(); public Keyword() { diff --git a/core/src/main/java/se/su/dsv/scipro/match/Match.java b/core/src/main/java/se/su/dsv/scipro/match/Match.java index ec4bb68099..2408e5058f 100755 --- a/core/src/main/java/se/su/dsv/scipro/match/Match.java +++ b/core/src/main/java/se/su/dsv/scipro/match/Match.java @@ -1,56 +1,85 @@ package se.su.dsv.scipro.match; import com.querydsl.core.annotations.QueryInit; +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; + import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.util.Objects; @Entity -@Cacheable(true) @Table(name = "idea_match") +@Cacheable(true) public class Match extends DomainObject { + + // ---------------------------------------------------------------------------------- + // basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne(optional = false) - private Idea idea; - - @ManyToOne - @QueryInit({"unit"}) - private User supervisor; - + @Basic @Enumerated(EnumType.STRING) private Idea.Status status; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (idea_match) referencing other tables. + // ---------------------------------------------------------------------------------- @ManyToOne(optional = true) + @JoinColumn(name = "changed_by_user_id", referencedColumnName = "id") private User changedBy; - public User getSupervisor() { - return supervisor; - } + @ManyToOne(optional = false) + @JoinColumn(name = "idea_id", referencedColumnName = "id") + private Idea idea; + @ManyToOne + @JoinColumn(name = "supervisor_user_id", referencedColumnName = "id") + @QueryInit({"unit"}) + private User supervisor; + + // ---------------------------------------------------------------------------------- + // getters and setters + // ---------------------------------------------------------------------------------- @Override public Long getId() { return this.id; } - public Idea getIdea() { - return this.idea; + public void setId(Long id) { + this.id = id; } public Idea.Status getStatus() { return this.status; } + public void setStatus(Idea.Status status) { + this.status = status; + } + public User getChangedBy() { return this.changedBy; } - public void setId(Long id) { - this.id = id; + public void setChangedBy(User changedBy) { + this.changedBy = changedBy; + } + + public Idea getIdea() { + return this.idea; } public void setIdea(Idea idea) { @@ -61,14 +90,13 @@ public class Match extends DomainObject { this.supervisor = supervisor; } - public void setStatus(Idea.Status status) { - this.status = status; - } - - public void setChangedBy(User changedBy) { - this.changedBy = changedBy; + public User getSupervisor() { + return supervisor; } + // ---------------------------------------------------------------------------------- + // other methods + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -93,6 +121,7 @@ public class Match extends DomainObject { @Override public String toString() { - return "Match(id=" + this.getId() + ", supervisor=" + this.getSupervisor() + ", status=" + this.getStatus() + ", changedBy=" + this.getChangedBy() + ")"; + return "Match(id=" + this.getId() + ", supervisor=" + this.getSupervisor() + ", status=" + this.getStatus() + + ", changedBy=" + this.getChangedBy() + ")"; } } diff --git a/core/src/main/java/se/su/dsv/scipro/match/PreliminaryMatch.java b/core/src/main/java/se/su/dsv/scipro/match/PreliminaryMatch.java index 5845f8f479..4a2b0229ba 100644 --- a/core/src/main/java/se/su/dsv/scipro/match/PreliminaryMatch.java +++ b/core/src/main/java/se/su/dsv/scipro/match/PreliminaryMatch.java @@ -1,70 +1,98 @@ package se.su.dsv.scipro.match; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; + import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.util.Objects; @Entity @Table(name = "preliminary_match") public class PreliminaryMatch extends DomainObject { + // ---------------------------------------------------------------------------------- + // basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Basic + @Column(name = "comment") + private String comment; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (idea_first_meeting) referencing other + // tables. + // ---------------------------------------------------------------------------------- @ManyToOne + @JoinColumn(name = "idea_id", referencedColumnName = "id") private Idea idea; @ManyToOne + @JoinColumn(name = "supervisor_user_id", referencedColumnName = "id") private User supervisor; - private String comment; - - // JPA - public PreliminaryMatch() { - } + // ---------------------------------------------------------------------------------- + // constructors + // ---------------------------------------------------------------------------------- + public PreliminaryMatch() { } public PreliminaryMatch(final Idea idea) { this.idea = idea; } + // ---------------------------------------------------------------------------------- + // getters and setters + // ---------------------------------------------------------------------------------- @Override public Long getId() { return this.id; } - public Idea getIdea() { - return this.idea; - } - - public User getSupervisor() { - return this.supervisor; - } - - public String getComment() { - return this.comment; - } - public void setId(Long id) { this.id = id; } - public void setIdea(Idea idea) { - this.idea = idea; - } - - public void setSupervisor(User supervisor) { - this.supervisor = supervisor; + public String getComment() { + return this.comment; } public void setComment(String comment) { this.comment = comment; } + public Idea getIdea() { + return this.idea; + } + + public void setIdea(Idea idea) { + this.idea = idea; + } + + public User getSupervisor() { + return this.supervisor; + } + + public void setSupervisor(User supervisor) { + this.supervisor = supervisor; + } + + // ---------------------------------------------------------------------------------- + // other methods + // ---------------------------------------------------------------------------------- @Override public String toString() { - return "PreliminaryMatch(id=" + this.getId() + ", idea=" + this.getIdea() + ", supervisor=" + this.getSupervisor() + ", comment=" + this.getComment() + ")"; + return "PreliminaryMatch(id=" + this.getId() + ", idea=" + this.getIdea() + ", supervisor=" + + this.getSupervisor() + ", comment=" + this.getComment() + ")"; } @Override diff --git a/core/src/main/java/se/su/dsv/scipro/match/Target.java b/core/src/main/java/se/su/dsv/scipro/match/Target.java index 2be7fac981..79d88f4514 100644 --- a/core/src/main/java/se/su/dsv/scipro/match/Target.java +++ b/core/src/main/java/se/su/dsv/scipro/match/Target.java @@ -20,12 +20,12 @@ public class Target implements Serializable { @MapsId("applicationPeriodId") @ManyToOne - @JoinColumn(name = "applicationPeriodId") + @JoinColumn(name = "application_period_id") private ApplicationPeriod applicationPeriod; @MapsId("projectTypeId") @ManyToOne - @JoinColumn(name = "projectTypeId") + @JoinColumn(name = "project_type_id") private ProjectType projectType; private int target; diff --git a/core/src/main/java/se/su/dsv/scipro/milestones/dataobjects/Milestone.java b/core/src/main/java/se/su/dsv/scipro/milestones/dataobjects/Milestone.java index 45bbd74bfb..f72cf1954f 100644 --- a/core/src/main/java/se/su/dsv/scipro/milestones/dataobjects/Milestone.java +++ b/core/src/main/java/se/su/dsv/scipro/milestones/dataobjects/Milestone.java @@ -1,39 +1,54 @@ package se.su.dsv.scipro.milestones.dataobjects; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; import se.su.dsv.scipro.data.dataobjects.Member; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.util.Collections; import java.util.List; @Entity @Table(name = "milestone") public class Milestone extends DomainObject { - + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) protected long id; - @ManyToOne - private Project project; - - @ManyToOne(optional = true) - private User user; - - @ManyToOne(optional = false) - private MilestoneActivityTemplate activity; - + @Basic @Column(name = "confirmed", nullable = false) private boolean confirmed = false; - @Override - public Long getId() { - return id; - } + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (milestone) referencing other tables. + // ---------------------------------------------------------------------------------- + @ManyToOne(optional = false) + @JoinColumn(name = "milestone_activity_template_id", referencedColumnName = "id") + private MilestoneActivityTemplate activity; + @ManyToOne + @JoinColumn(name = "project_id", referencedColumnName = "id") + private Project project; + + @ManyToOne(optional = true) + @JoinColumn(name = "user_id", referencedColumnName = "id") + private User user; + + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- protected Milestone() { } @@ -49,6 +64,15 @@ public class Milestone extends DomainObject { this.activity = activity; } + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- + + @Override + public Long getId() { + return id; + } + public void setId(Long id) { this.id = id; } @@ -61,14 +85,6 @@ public class Milestone extends DomainObject { this.confirmed = confirmed; } - public Project getProject() { - return project; - } - - public void setProject(Project project) { - this.project = project; - } - public MilestoneActivityTemplate getActivity() { return activity; } @@ -77,11 +93,22 @@ public class Milestone extends DomainObject { this.activity = activity; } - public List<Member> getMembers() { - return Collections.singletonList(new Member(user, Member.Type.MILESTONE_INDIVIDUAL)); + public Project getProject() { + return project; + } + + public void setProject(Project project) { + this.project = project; } public User getUser() { return this.user; } + + // ---------------------------------------------------------------------------------- + // Other methods + // ---------------------------------------------------------------------------------- + public List<Member> getMembers() { + return Collections.singletonList(new Member(user, Member.Type.MILESTONE_INDIVIDUAL)); + } } diff --git a/core/src/main/java/se/su/dsv/scipro/milestones/dataobjects/MilestoneActivityTemplate.java b/core/src/main/java/se/su/dsv/scipro/milestones/dataobjects/MilestoneActivityTemplate.java index f86421e861..583c558278 100644 --- a/core/src/main/java/se/su/dsv/scipro/milestones/dataobjects/MilestoneActivityTemplate.java +++ b/core/src/main/java/se/su/dsv/scipro/milestones/dataobjects/MilestoneActivityTemplate.java @@ -1,10 +1,23 @@ package se.su.dsv.scipro.milestones.dataobjects; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; import se.su.dsv.scipro.system.Event; import se.su.dsv.scipro.system.LazyDeletableDomainObject; import se.su.dsv.scipro.system.ProjectType; -import jakarta.persistence.*; import java.io.Serializable; import java.util.Comparator; import java.util.HashSet; @@ -18,42 +31,66 @@ public class MilestoneActivityTemplate extends LazyDeletableDomainObject { public static final String PEER_REVIEW_ONE = "PEER_REVIEW_ONE"; public static final String PEER_REVIEW_TWO = "PEER_REVIEW_TWO"; + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Basic(optional = false) + @Column(name = "title") private String title; @Basic(optional = true) + @Column(name = "description") private String description; @Enumerated(EnumType.STRING) + @Column(name = "type") private Type type; - @Column(unique = true) + @Basic + @Column(name = "code", unique = true) private String code; + @Basic + @Column(name = "sort_order") + private int sortOrder; + + @Basic + @Column(name = "editable_by_students") + private boolean editableByStudents = false; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (milestone_activity_template) + // referencing other tables. + // ---------------------------------------------------------------------------------- + @ManyToOne + @JoinColumn(name = "milestone_phase_template_id", referencedColumnName = "id", nullable = false) + private MilestonePhaseTemplate milestonePhaseTemplate; + + @OneToOne + @JoinColumn(name = "activated_by_event_name", referencedColumnName = "name") + private Event activatedBy; + + // ---------------------------------------------------------------------------------- + // @ManyToMany JPA-mappings + // ---------------------------------------------------------------------------------- + + // Many-to-Many between table milestone_activity_template and project_type through + // table "milestone_activity_template_project_type". @ManyToMany @JoinTable( - joinColumns = @JoinColumn(name = "milestone_activity_template_id") + name = "milestone_activity_template_project_type", + joinColumns = @JoinColumn(name = "milestone_activity_template_id"), + inverseJoinColumns = @JoinColumn(name = "project_type_id") ) private Set<ProjectType> projectTypes = new HashSet<>(); - @ManyToOne - @JoinColumn(name = "phase", nullable = false) - private MilestonePhaseTemplate milestonePhaseTemplate; - - @Column - private int sortOrder; - - @Column - private boolean editableByStudents = false; - - @OneToOne - @JoinColumn(name = "activatedBy") - private Event activatedBy; - + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- public MilestoneActivityTemplate() { } @@ -67,10 +104,9 @@ public class MilestoneActivityTemplate extends LazyDeletableDomainObject { this.description = description; } - public void addProjectType(ProjectType projectType) { - projectTypes.add(projectType); - } - + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- @Override public Long getId() { return this.id; @@ -80,79 +116,95 @@ public class MilestoneActivityTemplate extends LazyDeletableDomainObject { return this.title; } - public String getDescription() { - return this.description; - } - - public Type getType() { - return this.type; - } - - public String getCode() { - return this.code; - } - - public Set<ProjectType> getProjectTypes() { - return this.projectTypes; - } - - public MilestonePhaseTemplate getMilestonePhaseTemplate() { - return this.milestonePhaseTemplate; - } - - public int getSortOrder() { - return this.sortOrder; - } - - public boolean isEditableByStudents() { - return this.editableByStudents; - } - - public Event getActivatedBy() { - return this.activatedBy; - } - public void setTitle(String title) { this.title = title; } + public String getDescription() { + return this.description; + } + public void setDescription(String description) { this.description = description; } + public Type getType() { + return this.type; + } + public void setType(Type type) { this.type = type; } + public String getCode() { + return this.code; + } + public void setCode(String code) { this.code = code; } - public void setMilestonePhaseTemplate(MilestonePhaseTemplate milestonePhaseTemplate) { - this.milestonePhaseTemplate = milestonePhaseTemplate; + public int getSortOrder() { + return this.sortOrder; } public void setSortOrder(int sortOrder) { this.sortOrder = sortOrder; } + public boolean isEditableByStudents() { + return this.editableByStudents; + } + public void setEditableByStudents(boolean editableByStudents) { this.editableByStudents = editableByStudents; } + public MilestonePhaseTemplate getMilestonePhaseTemplate() { + return this.milestonePhaseTemplate; + } + + public void setMilestonePhaseTemplate(MilestonePhaseTemplate milestonePhaseTemplate) { + this.milestonePhaseTemplate = milestonePhaseTemplate; + } + + public Event getActivatedBy() { + return this.activatedBy; + } + public void setActivatedBy(Event activatedBy) { this.activatedBy = activatedBy; } + public Set<ProjectType> getProjectTypes() { + return this.projectTypes; + } + public void setProjectTypes(Set<ProjectType> projectTypes) { this.projectTypes = projectTypes; } - public static class BySortOrderComparator implements Comparator<MilestoneActivityTemplate>, Serializable { + // ---------------------------------------------------------------------------------- + // Other methods + // ---------------------------------------------------------------------------------- + public void addProjectType(ProjectType projectType) { + projectTypes.add(projectType); + } + + public boolean isAutomatic() { + return code != null || activatedBy != null; + } + + // ---------------------------------------------------------------------------------- + // Nested classes and types + // ---------------------------------------------------------------------------------- + public static class BySortOrderComparator implements Comparator<MilestoneActivityTemplate>, + Serializable { @Override public int compare(MilestoneActivityTemplate o1, MilestoneActivityTemplate o2) { int sortOrderResult = o1.sortOrder - o2.sortOrder; - int phaseSortOrderResult = o1.milestonePhaseTemplate.getSortOrder() - o2.getMilestonePhaseTemplate().getSortOrder(); + int phaseSortOrderResult = o1.milestonePhaseTemplate.getSortOrder() - + o2.getMilestonePhaseTemplate().getSortOrder(); if (phaseSortOrderResult == 0) { return sortOrderResult; @@ -175,8 +227,4 @@ public class MilestoneActivityTemplate extends LazyDeletableDomainObject { return asString; } } - - public boolean isAutomatic() { - return code != null || activatedBy != null; - } } diff --git a/core/src/main/java/se/su/dsv/scipro/milestones/dataobjects/MilestonePhaseTemplate.java b/core/src/main/java/se/su/dsv/scipro/milestones/dataobjects/MilestonePhaseTemplate.java index 3078dd4d24..34b29d2fe4 100644 --- a/core/src/main/java/se/su/dsv/scipro/milestones/dataobjects/MilestonePhaseTemplate.java +++ b/core/src/main/java/se/su/dsv/scipro/milestones/dataobjects/MilestonePhaseTemplate.java @@ -1,31 +1,41 @@ package se.su.dsv.scipro.milestones.dataobjects; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; import se.su.dsv.scipro.system.LazyDeletableDomainObject; -import jakarta.persistence.*; import java.util.Objects; @Entity @Table(name = "milestone_phase_template") public class MilestonePhaseTemplate extends LazyDeletableDomainObject { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) protected long id; - @Override - public Long getId() { - return id; - } - @Basic(optional = false) + @Column(name = "title") private String title; @Basic(optional = true) + @Column(name = "description") private String description; - @Column(name = "sortOrder") + @Basic + @Column(name = "sort_order") private int sortOrder; + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- public MilestonePhaseTemplate() { } @@ -41,37 +51,47 @@ public class MilestonePhaseTemplate extends LazyDeletableDomainObject { this.sortOrder = sortOrder; } - public String getTitle() { - return this.title; - } - - public String getDescription() { - return this.description; - } - - public int getSortOrder() { - return this.sortOrder; + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- + @Override + public Long getId() { + return id; } public void setId(long id) { this.id = id; } + public String getTitle() { + return this.title; + } + public void setTitle(String title) { this.title = title; } + public String getDescription() { + return this.description; + } + public void setDescription(String description) { this.description = description; } + public int getSortOrder() { + return this.sortOrder; + } + public void setSortOrder(int sortOrder) { this.sortOrder = sortOrder; } - @Override - public String toString() { - return "MilestonePhaseTemplate(id=" + this.getId() + ", title=" + this.getTitle() + ", description=" + this.getDescription() + ", sortOrder=" + this.getSortOrder() + ")"; + // ---------------------------------------------------------------------------------- + // Methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof MilestonePhaseTemplate; } @Override @@ -86,12 +106,13 @@ public class MilestonePhaseTemplate extends LazyDeletableDomainObject { && this.getSortOrder() == other.getSortOrder(); } - protected boolean canEqual(final Object other) { - return other instanceof MilestonePhaseTemplate; - } - @Override public int hashCode() { return Objects.hash(this.getId(), this.getTitle(), this.getDescription(), this.getSortOrder()); } + + @Override + public String toString() { + return "MilestonePhaseTemplate(id=" + this.getId() + ", title=" + this.getTitle() + ", description=" + this.getDescription() + ", sortOrder=" + this.getSortOrder() + ")"; + } } diff --git a/core/src/main/java/se/su/dsv/scipro/milestones/service/MilestoneActivator.java b/core/src/main/java/se/su/dsv/scipro/milestones/service/MilestoneActivator.java index d19f65687a..e70062e7b1 100644 --- a/core/src/main/java/se/su/dsv/scipro/milestones/service/MilestoneActivator.java +++ b/core/src/main/java/se/su/dsv/scipro/milestones/service/MilestoneActivator.java @@ -61,7 +61,7 @@ public class MilestoneActivator { int minimumActiveParticipationsToBeGraded = event.getProject() .getProjectType() .getProjectTypeSettings() - .getMinimumActiveParticipationsToBeGraded(); + .getMinActiveParticipationsToBeGraded(); if (completedParticipations >= minimumActiveParticipationsToBeGraded) { activateIndividualMilestone(Set.of("ParticipationGradingEvent"), event.getProject(), event.getStudent()); } else { diff --git a/core/src/main/java/se/su/dsv/scipro/nonworkperiod/NonWorkDayPeriod.java b/core/src/main/java/se/su/dsv/scipro/nonworkperiod/NonWorkDayPeriod.java index b12335ead6..639da2f1f5 100755 --- a/core/src/main/java/se/su/dsv/scipro/nonworkperiod/NonWorkDayPeriod.java +++ b/core/src/main/java/se/su/dsv/scipro/nonworkperiod/NonWorkDayPeriod.java @@ -1,24 +1,29 @@ package se.su.dsv.scipro.nonworkperiod; -import jakarta.persistence.GenerationType; -import se.su.dsv.scipro.system.DomainObject; - import jakarta.persistence.Cacheable; +import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.Table; +import se.su.dsv.scipro.system.DomainObject; + import java.time.LocalDate; import java.util.Objects; @Entity @Cacheable(true) +@Table(name = "non_work_day_period") public class NonWorkDayPeriod extends DomainObject { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Column(name = "start_date") private LocalDate startDate; + @Column(name = "end_date") private LocalDate endDate; private String comment; diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/CustomEvent.java b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/CustomEvent.java index 3fd7e4a0ac..f738fbf6c8 100644 --- a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/CustomEvent.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/CustomEvent.java @@ -1,5 +1,7 @@ package se.su.dsv.scipro.notifications.dataobject; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; import se.su.dsv.scipro.system.DomainObject; import jakarta.persistence.Entity; @@ -13,6 +15,8 @@ public class CustomEvent extends NotificationEvent { IDEA_DELETED } + @Basic + @Column(name = "event") @Enumerated(EnumType.STRING) private CustomEvent.Event event; diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/GroupEvent.java b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/GroupEvent.java index fa25851094..079c0cb09a 100644 --- a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/GroupEvent.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/GroupEvent.java @@ -1,5 +1,8 @@ package se.su.dsv.scipro.notifications.dataobject; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.JoinColumn; import se.su.dsv.scipro.group.Group; import se.su.dsv.scipro.system.DomainObject; @@ -11,37 +14,40 @@ import jakarta.persistence.ManyToOne; @Entity public class GroupEvent extends NotificationEvent { - public void setEvent(Event event) { - this.event = event; - } - public enum Event { MESSAGE_THREAD_CREATED, MESSAGE_THREAD_REPLY } + @Basic + @Column(name = "event") + @Enumerated(EnumType.STRING) + private Event event; + + @ManyToOne + @JoinColumn(name = "project_group_id", referencedColumnName = "id") + private Group group; + + public GroupEvent() { + super(Notification.Type.GROUP); + } + + @Override + public Enum getEvent() { + return event; + } + + public void setEvent(Event event) { + this.event = event; + } + public Group getGroup() { return group; } - @ManyToOne - private Group group; - - @Enumerated(EnumType.STRING) - private Event event; - - public GroupEvent() { - super(Notification.Type.GROUP); - } - public void setGroup(Group group) { this.group = group; } - @Override - public Enum getEvent() { - return event; - } - @Override protected String getEntityTitle() { return group.getTitle(); diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/IdeaEvent.java b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/IdeaEvent.java index 8ef2b2d070..54df3b315e 100755 --- a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/IdeaEvent.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/IdeaEvent.java @@ -1,5 +1,8 @@ package se.su.dsv.scipro.notifications.dataobject; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.JoinColumn; import se.su.dsv.scipro.match.Idea; import se.su.dsv.scipro.system.DomainObject; @@ -11,18 +14,29 @@ import jakarta.persistence.ManyToOne; @Entity public class IdeaEvent extends NotificationEvent { - public enum Event { STATUS_CHANGE, PARTNER_ACCEPT, ADDED_AS_PARTNER, FIRST_MEETING, REMOVED_AS_PARTNER, EXPORTED_FAIL } - @ManyToOne - private Idea idea; - + @Basic + @Column(name = "event") @Enumerated(EnumType.STRING) private Event event; + @ManyToOne + @JoinColumn(name = "idea_id", referencedColumnName = "id") + private Idea idea; + + @Override + public Event getEvent() { + return event; + } + + public void setEvent(Event event) { + this.event = event; + } + public IdeaEvent() { super(Notification.Type.IDEA); } @@ -35,15 +49,6 @@ public class IdeaEvent extends NotificationEvent { this.idea = idea; } - @Override - public Event getEvent() { - return event; - } - - public void setEvent(Event event) { - this.event = event; - } - @Override public String getEntityTitle() { return idea.getTitle(); diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/MileStoneEvent.java b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/MileStoneEvent.java index 9e4c1bf5a9..f84a47be57 100644 --- a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/MileStoneEvent.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/MileStoneEvent.java @@ -1,5 +1,8 @@ package se.su.dsv.scipro.notifications.dataobject; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.JoinColumn; import se.su.dsv.scipro.milestones.dataobjects.Milestone; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.DomainObject; @@ -17,24 +20,64 @@ public class MileStoneEvent extends NotificationEvent { MILESTONE_CONFIRMED, MILESTONE_REVOKED } - @ManyToOne - private Milestone milestone; - + @Basic + @Column(name = "event") @Enumerated(EnumType.STRING) private Event event; + @ManyToOne + @JoinColumn(name = "milestone_id", referencedColumnName = "id") + private Milestone milestone; + public MileStoneEvent() { super(Notification.Type.MILESTONE); } @Override - public Project getProject() { - return milestone.getProject(); + public Enum getEvent() { + return event; + } + + public void setEvent(Event event) { + this.event = event; + } + + public Milestone getMilestone() { + return this.milestone; + } + + public void setMilestone(Milestone milestone) { + this.milestone = milestone; } @Override - public Enum getEvent() { - return event; + public boolean equals(final Object o) { + if (o == this) return true; + if (!(o instanceof MileStoneEvent)) return false; + final MileStoneEvent other = (MileStoneEvent) o; + return other.canEqual(this) + && super.equals(o) + && Objects.equals(this.getMilestone(), other.getMilestone()) + && Objects.equals(this.getEvent(), other.getEvent()); + } + + @Override + public int hashCode() { + return Objects.hash(this.getMilestone(), this.getEvent()); + } + + @Override + public String toString() { + return "MileStoneEvent(milestone=" + this.getMilestone() + ", event=" + this.getEvent() + ")"; + } + + protected boolean canEqual(final Object other) { + return other instanceof MileStoneEvent; + } + + @Override + public Project getProject() { + return milestone.getProject(); } @Override @@ -51,41 +94,4 @@ public class MileStoneEvent extends NotificationEvent { public DomainObject getEntity() { return milestone; } - - public Milestone getMilestone() { - return this.milestone; - } - - public void setMilestone(Milestone milestone) { - this.milestone = milestone; - } - - public void setEvent(Event event) { - this.event = event; - } - - @Override - public String toString() { - return "MileStoneEvent(milestone=" + this.getMilestone() + ", event=" + this.getEvent() + ")"; - } - - @Override - public boolean equals(final Object o) { - if (o == this) return true; - if (!(o instanceof MileStoneEvent)) return false; - final MileStoneEvent other = (MileStoneEvent) o; - return other.canEqual(this) - && super.equals(o) - && Objects.equals(this.getMilestone(), other.getMilestone()) - && Objects.equals(this.getEvent(), other.getEvent()); - } - - protected boolean canEqual(final Object other) { - return other instanceof MileStoneEvent; - } - - @Override - public int hashCode() { - return Objects.hash(this.getMilestone(), this.getEvent()); - } } diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/Notification.java b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/Notification.java index 073be08b40..5102db88cd 100755 --- a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/Notification.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/Notification.java @@ -1,41 +1,59 @@ package se.su.dsv.scipro.notifications.dataobject; +import jakarta.persistence.Basic; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; - @Entity +@Table(name = "notification") public class Notification extends DomainObject { - - public enum Type { - PROJECT, IDEA, FINAL_SEMINAR, PEER, MILESTONE, - GROUP, FORUM, CUSTOM - } - + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Basic(optional = false) - private boolean unread = true; - - @Basic(optional = false) + @Column(name = "mailed") private boolean mailed = false; + @Basic(optional = false) + @Column(name = "unread") + private boolean unread = true; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (notification) referencing other + // tables. + // ---------------------------------------------------------------------------------- @ManyToOne(cascade = CascadeType.ALL) - @JoinColumn(name = "notificationData_id") + @JoinColumn(name = "notification_data_id", referencedColumnName = "id") private NotificationEvent notificationEvent; @ManyToOne + @JoinColumn(name = "user_id", referencedColumnName = "id") private User user; + // ---------------------------------------------------------------------------------- + // Constructor + // ---------------------------------------------------------------------------------- public Notification() { - } + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- @Override public Long getId() { return id; @@ -45,6 +63,14 @@ public class Notification extends DomainObject { this.id = id; } + public boolean isMailed() { + return mailed; + } + + public void setMailed(boolean mailed) { + this.mailed = mailed; + } + public boolean isUnread() { return unread; } @@ -69,14 +95,9 @@ public class Notification extends DomainObject { this.user = user; } - public boolean isMailed() { - return mailed; - } - - public void setMailed(boolean mailed) { - this.mailed = mailed; - } - + // ---------------------------------------------------------------------------------- + // Other methods + // ---------------------------------------------------------------------------------- public String getTitle() { return getNotificationEvent().getTitle(); } @@ -108,4 +129,12 @@ public class Notification extends DomainObject { public User getCausedBy() { return getNotificationEvent().getCausedBy(); } + + // ---------------------------------------------------------------------------------- + // Nested type + // ---------------------------------------------------------------------------------- + public enum Type { + PROJECT, IDEA, FINAL_SEMINAR, PEER, MILESTONE, + GROUP, FORUM, CUSTOM + } } diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/NotificationEvent.java b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/NotificationEvent.java index 1aac89eca6..6eb2f15ef4 100755 --- a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/NotificationEvent.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/NotificationEvent.java @@ -1,55 +1,70 @@ package se.su.dsv.scipro.notifications.dataobject; +import jakarta.persistence.Basic; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.DiscriminatorColumn; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.util.Collection; @Entity +@Table(name = "notification_data") @Inheritance(strategy = InheritanceType.SINGLE_TABLE) -@Table(name = "NotificationData") +@DiscriminatorColumn(name = "subclass") public abstract class NotificationEvent extends DomainObject { - + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) protected long id; + @Basic + @Column(name = "type") @Enumerated(EnumType.STRING) protected Notification.Type type; - @OneToMany(mappedBy = "notificationEvent", cascade = CascadeType.ALL, orphanRemoval = true) - private Collection<Notification> notifications; - @Basic(optional = true) + @Column(name = "source") private String source; @Basic(optional = true) + @Column(name = "additional_source") private String additionalSource; - + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (notification_data) referencing other + // tables. + // ---------------------------------------------------------------------------------- @ManyToOne(optional = true) + @JoinColumn(name = "caused_by_user_id", referencedColumnName = "id") private User causedBy; - public abstract Enum getEvent(); - - /** - * The title of the entity this event is about. - * - * @return a human readable title - */ - protected abstract String getEntityTitle(); - - /** - * Return true if there is an entity backing this event. - * Used to determine if this event was about a deletion, or has since been deleted. - */ - public abstract boolean hasEntity(); - - public abstract DomainObject getEntity(); + // ---------------------------------------------------------------------------------- + // JPA-mappings of other tables referencing to this table "notification_data" + // ---------------------------------------------------------------------------------- + @OneToMany(mappedBy = "notificationEvent", cascade = CascadeType.ALL, orphanRemoval = true) + private Collection<Notification> notifications; + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- protected NotificationEvent() { } @@ -58,6 +73,9 @@ public abstract class NotificationEvent extends DomainObject { this.type = type; } + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- @Override public Long getId() { return id; @@ -75,14 +93,6 @@ public abstract class NotificationEvent extends DomainObject { this.type = type; } - public Collection<Notification> getNotifications() { - return notifications; - } - - public void setNotifications(Collection<Notification> notifications) { - this.notifications = notifications; - } - public String getSource() { return source; } @@ -91,8 +101,12 @@ public abstract class NotificationEvent extends DomainObject { this.source = source; } - public String getTitle() { - return hasEntity() ? getEntityTitle() : "[Deleted entity]"; + public String getAdditionalSource() { + return additionalSource; + } + + public void setAdditionalSource(String additionalSource) { + this.additionalSource = additionalSource; } public User getCausedBy() { @@ -103,6 +117,41 @@ public abstract class NotificationEvent extends DomainObject { this.causedBy = user; } + public Collection<Notification> getNotifications() { + return notifications; + } + + public void setNotifications(Collection<Notification> notifications) { + this.notifications = notifications; + } + + // ---------------------------------------------------------------------------------- + // Abstract methods to be implemented by subclasses + // ---------------------------------------------------------------------------------- + /** + * The title of the entity this event is about. + * + * @return a human readable title + */ + protected abstract String getEntityTitle(); + + /** + * Return true if there is an entity backing this event. + * Used to determine if this event was about a deletion, or has since been deleted. + */ + public abstract boolean hasEntity(); + + public abstract DomainObject getEntity(); + + public abstract Enum getEvent(); + + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- + public String getTitle() { + return hasEntity() ? getEntityTitle() : "[Deleted entity]"; + } + /** * Override this method if the event has an association with a {@link Project}. * @@ -111,12 +160,4 @@ public abstract class NotificationEvent extends DomainObject { public Project getProject() { return null; } - - public String getAdditionalSource() { - return additionalSource; - } - - public void setAdditionalSource(String additionalSource) { - this.additionalSource = additionalSource; - } } diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/PeerEvent.java b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/PeerEvent.java index 17272c9768..8ca7f15e9e 100755 --- a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/PeerEvent.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/PeerEvent.java @@ -1,5 +1,8 @@ package se.su.dsv.scipro.notifications.dataobject; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.JoinColumn; import se.su.dsv.scipro.peer.PeerReview; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.DomainObject; @@ -12,22 +15,31 @@ import jakarta.persistence.ManyToOne; @Entity public class PeerEvent extends NotificationEvent { - public enum Event { REVIEW_COMPLETED, REVIEW_COMMENT, REVIEW_ACCEPTED, REQUEST_DELETED, - REQUEST_EXPIRED } - - @ManyToOne - private PeerReview review; + public enum Event { + REVIEW_COMPLETED, REVIEW_COMMENT, REVIEW_ACCEPTED, REQUEST_DELETED, + REQUEST_EXPIRED + } + @Basic + @Column(name = "event") @Enumerated(EnumType.STRING) private Event event; + @ManyToOne + @JoinColumn(name = "peer_review_id", referencedColumnName = "id") + private PeerReview review; + public PeerEvent() { super(Notification.Type.PEER); } @Override - public Project getProject() { - return review.getProject(); + public Event getEvent() { + return event; + } + + public void setEvent(Event event) { + this.event = event; } public PeerReview getReview() { @@ -39,12 +51,8 @@ public class PeerEvent extends NotificationEvent { } @Override - public Event getEvent() { - return event; - } - - public void setEvent(Event event) { - this.event = event; + public Project getProject() { + return review.getProject(); } @Override diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/PeerRequestEvent.java b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/PeerRequestEvent.java index 37355d4d44..72f6dac062 100644 --- a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/PeerRequestEvent.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/PeerRequestEvent.java @@ -1,5 +1,8 @@ package se.su.dsv.scipro.notifications.dataobject; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.JoinColumn; import se.su.dsv.scipro.peer.PeerRequest; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.DomainObject; @@ -12,10 +15,13 @@ import jakarta.persistence.ManyToOne; @Entity public class PeerRequestEvent extends NotificationEvent { + @Basic + @Column(name = "event") @Enumerated(EnumType.STRING) private PeerEvent.Event event; @ManyToOne + @JoinColumn(name = "peer_request_id", referencedColumnName = "id") private PeerRequest request; public PeerRequestEvent() { diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/ProjectEvent.java b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/ProjectEvent.java index c8c3e51032..a44a3760be 100755 --- a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/ProjectEvent.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/ProjectEvent.java @@ -1,5 +1,8 @@ package se.su.dsv.scipro.notifications.dataobject; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.JoinColumn; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.DomainObject; @@ -19,29 +22,23 @@ public class ProjectEvent extends NotificationEvent { FINAL_SEMINAR_APPROVAL_APPROVED, FINAL_SEMINAR_APPROVAL_REJECTED, ROUGH_DRAFT_APPROVAL_REQUESTED, ROUGH_DRAFT_APPROVAL_APPROVED, ROUGH_DRAFT_APPROVAL_REJECTED, REVIEWER_GRADING_REPORT_SUBMITTED, ONE_YEAR_PASSED_FROM_LATEST_ANNUAL_REVIEW, SUPERVISOR_GRADING_INITIAL_ASSESSMENT_DONE, - EXPORTED_SUCCESS, REVIEWER_GRADING_INITIAL_ASSESSMENT_DONE, FIRST_MEETING, OPPOSITION_FAILED, PARTICIPATION_APPROVED, COMPLETED, - PARTICIPATION_FAILED + EXPORTED_SUCCESS, REVIEWER_GRADING_INITIAL_ASSESSMENT_DONE, FIRST_MEETING, OPPOSITION_FAILED, + PARTICIPATION_APPROVED, COMPLETED, PARTICIPATION_FAILED } - @ManyToOne - private Project project; - + @Basic + @Column(name = "event") @Enumerated(EnumType.STRING) private Event event; + @ManyToOne + @JoinColumn(name = "project_id", referencedColumnName = "id") + private Project project; + public ProjectEvent() { super(Notification.Type.PROJECT); } - @Override - public Project getProject() { - return project; - } - - public void setProject(Project project) { - this.project = project; - } - @Override public Event getEvent() { return event; @@ -51,6 +48,15 @@ public class ProjectEvent extends NotificationEvent { this.event = event; } + @Override + public Project getProject() { + return project; + } + + public void setProject(Project project) { + this.project = project; + } + @Override public String getEntityTitle() { return project.getTitle(); diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/ProjectForumEvent.java b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/ProjectForumEvent.java index a5b2989c19..c95ec8bf05 100644 --- a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/ProjectForumEvent.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/ProjectForumEvent.java @@ -1,5 +1,8 @@ package se.su.dsv.scipro.notifications.dataobject; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.JoinColumn; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.DomainObject; @@ -10,29 +13,24 @@ import jakarta.persistence.ManyToOne; @Entity public class ProjectForumEvent extends NotificationEvent { - @ManyToOne - private Project project; - - @Enumerated(EnumType.STRING) - private Event event; - - public void setProject(Project project) { - this.project = project; - } public enum Event { NEW_FORUM_POST, NEW_FORUM_POST_COMMENT, NEW_REVIEWER_INTERACTION } + @Basic + @Column(name = "event") + @Enumerated(EnumType.STRING) + private Event event; + + @ManyToOne + @JoinColumn(name = "project_id", referencedColumnName = "id") + private Project project; + public ProjectForumEvent() { super(Notification.Type.FORUM); } - @Override - public Project getProject() { - return this.project; - } - @Override public Event getEvent() { return event; @@ -42,6 +40,15 @@ public class ProjectForumEvent extends NotificationEvent { this.event = event; } + @Override + public Project getProject() { + return this.project; + } + + public void setProject(Project project) { + this.project = project; + } + @Override protected String getEntityTitle() { return project.getTitle(); @@ -56,5 +63,4 @@ public class ProjectForumEvent extends NotificationEvent { public DomainObject getEntity() { return project; } - } diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/SeminarEvent.java b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/SeminarEvent.java index 46951edcc3..dedad4ca0a 100755 --- a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/SeminarEvent.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/SeminarEvent.java @@ -1,5 +1,8 @@ package se.su.dsv.scipro.notifications.dataobject; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.JoinColumn; import se.su.dsv.scipro.finalseminar.FinalSeminar; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.DomainObject; @@ -12,27 +15,24 @@ import jakarta.persistence.ManyToOne; @Entity public class SeminarEvent extends NotificationEvent { - public enum Event { CREATED, ROOM_CHANGED, DATE_CHANGED, OPPOSITION_CHANGED, PARTICIPATION_CHANGED, THESIS_UPLOADED, THESIS_UPLOADED_OPPONENT, - OPPOSITION_REPORT_UPLOADED, THESIS_DELETED, THESIS_UPLOAD_REMIND, CANCELLED} - - @ManyToOne - private FinalSeminar seminar; + public enum Event { CREATED, ROOM_CHANGED, DATE_CHANGED, OPPOSITION_CHANGED, + PARTICIPATION_CHANGED, THESIS_UPLOADED, THESIS_UPLOADED_OPPONENT, + OPPOSITION_REPORT_UPLOADED, THESIS_DELETED, THESIS_UPLOAD_REMIND, CANCELLED + } + @Basic + @Column(name = "event") @Enumerated(EnumType.STRING) private Event event; + @ManyToOne + @JoinColumn(name = "final_seminar_id", referencedColumnName = "id") + private FinalSeminar seminar; + public SeminarEvent() { super(Notification.Type.FINAL_SEMINAR); } - public FinalSeminar getSeminar() { - return seminar; - } - - public void setSeminar(FinalSeminar seminar) { - this.seminar = seminar; - } - @Override public Event getEvent() { return event; @@ -42,6 +42,14 @@ public class SeminarEvent extends NotificationEvent { this.event = event; } + public FinalSeminar getSeminar() { + return seminar; + } + + public void setSeminar(FinalSeminar seminar) { + this.seminar = seminar; + } + @Override public String getEntityTitle() { return seminar.getProject().getTitle(); diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/settings/entities/DeliveryConfiguration.java b/core/src/main/java/se/su/dsv/scipro/notifications/settings/entities/DeliveryConfiguration.java index 65af5aaa5c..7e20fa7ffb 100644 --- a/core/src/main/java/se/su/dsv/scipro/notifications/settings/entities/DeliveryConfiguration.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/settings/entities/DeliveryConfiguration.java @@ -1,14 +1,21 @@ package se.su.dsv.scipro.notifications.settings.entities; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; + import se.su.dsv.scipro.notifications.dataobject.Notification; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; - @Entity @Table(name = "notification_delivery_configuration", uniqueConstraints = { - @UniqueConstraint(name = "one_setting_per_user", columnNames = {"type", "event", "method", "user_id"}) + @UniqueConstraint(name = "uk_one_setting_per_user", columnNames = {"type", "event", "method", "user_id"}) }) public class DeliveryConfiguration extends Configuration { diff --git a/core/src/main/java/se/su/dsv/scipro/peer/Answer.java b/core/src/main/java/se/su/dsv/scipro/peer/Answer.java index fd7b4b0ca4..bf40f7d72e 100755 --- a/core/src/main/java/se/su/dsv/scipro/peer/Answer.java +++ b/core/src/main/java/se/su/dsv/scipro/peer/Answer.java @@ -1,80 +1,115 @@ package se.su.dsv.scipro.peer; +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Lob; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; import se.su.dsv.scipro.checklist.ChecklistAnswerEnum; import se.su.dsv.scipro.system.DomainObject; -import jakarta.persistence.*; import java.util.Objects; @Entity @Table(name="answer") @Cacheable(true) public class Answer extends DomainObject { + // ---------------------------------------------------------------------------------- + // basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - + + @Basic(optional = false) + @Column(name = "question") + private String question; + + @Enumerated(EnumType.STRING) + @Column(name = "answer", nullable=false) + private ChecklistAnswerEnum answer = ChecklistAnswerEnum.NO_ANSWER; + + @Basic(optional=true) + @Lob + @Column(name = "motivation") + private String motivation; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (answer) referencing other tables. + // ---------------------------------------------------------------------------------- @ManyToOne(optional=false) + @JoinColumn(name = "peer_review_id", referencedColumnName = "id") private PeerReview peerReview; - @Basic(optional = false) - private String question; - - @Lob - @Basic(optional=true) - private String motivation; - - @Enumerated(EnumType.STRING) - @Column(nullable=false) - private ChecklistAnswerEnum answer = ChecklistAnswerEnum.NO_ANSWER; - + // ---------------------------------------------------------------------------------- + // constructors + // ---------------------------------------------------------------------------------- public Answer() {} + public Answer(PeerReview peerReview, String question){ this.peerReview = peerReview; this.question = question; } + // ---------------------------------------------------------------------------------- + // getters and setters + // ---------------------------------------------------------------------------------- @Override public Long getId() { return this.id; } - public PeerReview getPeerReview() { - return this.peerReview; - } - - public String getQuestion() { - return this.question; - } - - public String getMotivation() { - return this.motivation; - } - - public ChecklistAnswerEnum getAnswer() { - return this.answer; - } - public void setId(Long id) { this.id = id; } - public void setPeerReview(PeerReview peerReview) { - this.peerReview = peerReview; + public String getQuestion() { + return this.question; } public void setQuestion(String question) { this.question = question; } - public void setMotivation(String motivation) { - this.motivation = motivation; + public ChecklistAnswerEnum getAnswer() { + return this.answer; } public void setAnswer(ChecklistAnswerEnum answer) { this.answer = answer; } + public String getMotivation() { + return this.motivation; + } + + public void setMotivation(String motivation) { + this.motivation = motivation; + } + + public PeerReview getPeerReview() { + return this.peerReview; + } + + public void setPeerReview(PeerReview peerReview) { + this.peerReview = peerReview; + } + + // ---------------------------------------------------------------------------------- + // other methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof Answer; + } + @Override public boolean equals(final Object o) { if (o == this) return true; @@ -84,10 +119,6 @@ public class Answer extends DomainObject { && Objects.equals(this.getId(), other.getId()); } - protected boolean canEqual(final Object other) { - return other instanceof Answer; - } - @Override public int hashCode() { return Objects.hashCode(this.getId()); @@ -95,6 +126,7 @@ public class Answer extends DomainObject { @Override public String toString() { - return "Answer(id=" + this.getId() + ", question=" + this.getQuestion() + ", motivation=" + this.getMotivation() + ", answer=" + this.getAnswer() + ")"; + return "Answer(id=" + this.getId() + ", question=" + this.getQuestion() + ", motivation=" + + this.getMotivation() + ", answer=" + this.getAnswer() + ")"; } } diff --git a/core/src/main/java/se/su/dsv/scipro/peer/Comment.java b/core/src/main/java/se/su/dsv/scipro/peer/Comment.java index 32d3fe771d..bb5c68db96 100755 --- a/core/src/main/java/se/su/dsv/scipro/peer/Comment.java +++ b/core/src/main/java/se/su/dsv/scipro/peer/Comment.java @@ -1,9 +1,19 @@ package se.su.dsv.scipro.peer; +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Lob; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.io.Serializable; import java.util.Comparator; @@ -16,12 +26,16 @@ public class Comment extends DomainObject { private Long id; @ManyToOne(optional = false) + @JoinColumn(name = "creator_user_id", referencedColumnName = "id") private User creator; + @Basic + @Column(name = "comment") @Lob private String comment; @ManyToOne(optional = false) + @JoinColumn(name = "comment_thread_id", referencedColumnName = "id") private CommentThread commentThread; protected Comment() { diff --git a/core/src/main/java/se/su/dsv/scipro/peer/CommentThread.java b/core/src/main/java/se/su/dsv/scipro/peer/CommentThread.java index d90511945c..803fb375af 100755 --- a/core/src/main/java/se/su/dsv/scipro/peer/CommentThread.java +++ b/core/src/main/java/se/su/dsv/scipro/peer/CommentThread.java @@ -8,7 +8,9 @@ import java.util.Set; import java.util.TreeSet; @Entity -@Table(name = "comment_thread", uniqueConstraints = {@UniqueConstraint(columnNames = {"commentableKey", "commentableId"})}) +@Table(name = "comment_thread", + uniqueConstraints = {@UniqueConstraint(name = "uk_comment_thread_id_key", + columnNames = {"commentable_key", "commentable_id"})}) @Cacheable(true) public class CommentThread extends DomainObject { @@ -16,11 +18,10 @@ public class CommentThread extends DomainObject { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Basic(optional = false) - @Column(length = 191) + @Column(name = "commentable_key", length = 191, nullable = false) private String commentableKey; - @Basic(optional = false) + @Column(name = "commentable_id", nullable = false) private Long commentableId; @OneToMany(mappedBy = "commentThread", orphanRemoval = true, cascade = CascadeType.ALL, targetEntity = Comment.class) diff --git a/core/src/main/java/se/su/dsv/scipro/peer/PeerRequest.java b/core/src/main/java/se/su/dsv/scipro/peer/PeerRequest.java index 8bf04b8d37..addf9fff54 100755 --- a/core/src/main/java/se/su/dsv/scipro/peer/PeerRequest.java +++ b/core/src/main/java/se/su/dsv/scipro/peer/PeerRequest.java @@ -1,7 +1,20 @@ package se.su.dsv.scipro.peer; import com.querydsl.core.annotations.QueryInit; +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Lob; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; import se.su.dsv.scipro.checklist.ChecklistTemplate; import se.su.dsv.scipro.data.dataobjects.Member; import se.su.dsv.scipro.file.FileReference; @@ -10,57 +23,138 @@ import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.Language; import se.su.dsv.scipro.system.User; -import jakarta.persistence.Basic; -import jakarta.persistence.Cacheable; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.Lob; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToMany; -import jakarta.persistence.Table; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; @Entity @Table(name = "peer_request") @Cacheable(true) public class PeerRequest extends DomainObject { + // ---------------------------------------------------------------------------------- + // basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Lob @Basic(optional = true) + @Lob + @Column(name = "comment") private String comment; - @ManyToOne(optional = false) - @QueryInit({"headSupervisor", "projectType"}) - private Project project; - - @ManyToOne(optional = false) - private User requester; - - @ManyToOne(optional = false) - @JoinColumn(name = "file_reference_id") - private FileReference file; - - @ManyToOne(optional = true) - private ChecklistTemplate checklistTemplate; + @Enumerated(EnumType.STRING) + @Column(name = "status", nullable = false) + private RequestStatus status = RequestStatus.WAITING; @Enumerated(EnumType.STRING) private Language language; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (peer_request) referencing other tables. + // ---------------------------------------------------------------------------------- + @ManyToOne(optional = true) + @JoinColumn(name = "checklist_template_id", referencedColumnName = "id") + private ChecklistTemplate checklistTemplate; + + @ManyToOne(optional = false) + @JoinColumn(name = "file_reference_id", referencedColumnName = "id") + private FileReference file; + + @ManyToOne(optional = false) + @JoinColumn(name = "project_id", referencedColumnName = "id") + @QueryInit({"headSupervisor", "projectType"}) + private Project project; + + @ManyToOne(optional = false) + @JoinColumn(name = "requester_user_id", referencedColumnName = "id") + private User requester; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of other tables referencing to this table "peer_request" + // ---------------------------------------------------------------------------------- @OneToMany(mappedBy = "peerRequest") private List<PeerReview> peerReviews = new ArrayList<>(1); - @Enumerated(EnumType.STRING) - @Column(nullable = false) - private RequestStatus status = RequestStatus.WAITING; + // ---------------------------------------------------------------------------------- + // getters and setters + // ---------------------------------------------------------------------------------- + @Override + public Long getId() { + return this.id; + } + public void setId(Long id) { + this.id = id; + } + + public String getComment() { + return this.comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public RequestStatus getStatus() { + return this.status; + } + + public void setStatus(RequestStatus status) { + this.status = status; + } + + public Language getLanguage() { + return this.language; + } + + public void setLanguage(Language language) { + this.language = language; + } + + public ChecklistTemplate getChecklistTemplate() { + return this.checklistTemplate; + } + + public void setChecklistTemplate(ChecklistTemplate checklistTemplate) { + this.checklistTemplate = checklistTemplate; + } + + public FileReference getFile() { + return this.file; + } + + public void setFile(FileReference file) { + this.file = file; + } + + public Project getProject() { + return this.project; + } + + public void setProject(Project project) { + this.project = project; + } + + public User getRequester() { + return this.requester; + } + + public void setRequester(User requester) { + this.requester = requester; + } + + public List<PeerReview> getPeerReviews() { + return this.peerReviews; + } + + public void setPeerReviews(List<PeerReview> peerReviews) { + this.peerReviews = peerReviews; + } + + // ---------------------------------------------------------------------------------- + // other methods + // ---------------------------------------------------------------------------------- public List<Member> getMembers() { List<Member> members = project.getMembers(); @@ -80,77 +174,8 @@ public class PeerRequest extends DomainObject { return null; } - @Override - public Long getId() { - return this.id; - } - - public String getComment() { - return this.comment; - } - - public Project getProject() { - return this.project; - } - - public User getRequester() { - return this.requester; - } - - public FileReference getFile() { - return this.file; - } - - public ChecklistTemplate getChecklistTemplate() { - return this.checklistTemplate; - } - - public Language getLanguage() { - return this.language; - } - - public List<PeerReview> getPeerReviews() { - return this.peerReviews; - } - - public RequestStatus getStatus() { - return this.status; - } - - public void setId(Long id) { - this.id = id; - } - - public void setComment(String comment) { - this.comment = comment; - } - - public void setProject(Project project) { - this.project = project; - } - - public void setRequester(User requester) { - this.requester = requester; - } - - public void setFile(FileReference file) { - this.file = file; - } - - public void setChecklistTemplate(ChecklistTemplate checklistTemplate) { - this.checklistTemplate = checklistTemplate; - } - - public void setLanguage(Language language) { - this.language = language; - } - - public void setPeerReviews(List<PeerReview> peerReviews) { - this.peerReviews = peerReviews; - } - - public void setStatus(RequestStatus status) { - this.status = status; + protected boolean canEqual(final Object other) { + return other instanceof PeerRequest; } @Override @@ -162,10 +187,6 @@ public class PeerRequest extends DomainObject { && Objects.equals(this.getId(), other.getId()); } - protected boolean canEqual(final Object other) { - return other instanceof PeerRequest; - } - @Override public int hashCode() { return Objects.hashCode(this.getId()); @@ -173,6 +194,9 @@ public class PeerRequest extends DomainObject { @Override public String toString() { - return "PeerRequest(id=" + this.getId() + ", comment=" + this.getComment() + ", project=" + this.getProject() + ", requester=" + this.getRequester() + ", file=" + this.getFile() + ", checklistTemplate=" + this.getChecklistTemplate() + ", language=" + this.getLanguage() + ", status=" + this.getStatus() + ")"; + return "PeerRequest(id=" + this.getId() + ", comment=" + this.getComment() + ", project=" + + this.getProject() + ", requester=" + this.getRequester() + ", file=" + this.getFile() + + ", checklistTemplate=" + this.getChecklistTemplate() + ", language=" + this.getLanguage() + + ", status=" + this.getStatus() + ")"; } } diff --git a/core/src/main/java/se/su/dsv/scipro/peer/PeerReview.java b/core/src/main/java/se/su/dsv/scipro/peer/PeerReview.java index e721778e38..7ce7378d1d 100755 --- a/core/src/main/java/se/su/dsv/scipro/peer/PeerReview.java +++ b/core/src/main/java/se/su/dsv/scipro/peer/PeerReview.java @@ -1,6 +1,24 @@ package se.su.dsv.scipro.peer; import com.querydsl.core.annotations.QueryInit; +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Lob; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.OrderBy; +import jakarta.persistence.Table; + import se.su.dsv.scipro.checklist.ChecklistAnswerEnum; import se.su.dsv.scipro.data.dataobjects.Member; import se.su.dsv.scipro.file.FileReference; @@ -8,7 +26,6 @@ import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -23,41 +40,140 @@ public class PeerReview extends DomainObject implements Commentable { public enum ReviewStatus { IN_PROGRESS, COMPLETED, EXPIRED } - + + // ---------------------------------------------------------------------------------- + // basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - + + @Basic + @Lob + @Column(name = "comment") + private String comment; + + @Enumerated(EnumType.STRING) + @Column(name = "status") + private ReviewStatus status = ReviewStatus.IN_PROGRESS; + + @Basic(optional = false) + @Column(name = "deadline") + private Date deadline; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (peer_review) referencing other tables. + // ---------------------------------------------------------------------------------- + @OneToOne(optional=true, orphanRemoval = true, cascade = CascadeType.ALL) + @JoinColumn(name = "file_reference_id", referencedColumnName = "id") + private FileReference file; + + @ManyToOne(optional=false) + @JoinColumn(name = "peer_request_id", referencedColumnName = "id") + @QueryInit({"project.headSupervisor", "requester.user", "language", "checklistTemplate"}) + private PeerRequest peerRequest; + + @ManyToOne(optional=false) + @JoinColumn(name = "project_id", referencedColumnName = "id") + @QueryInit({"headSupervisor", "projectType"}) + private Project project; + @ManyToOne(optional=false) + @JoinColumn(name = "reviewer_user_id", referencedColumnName = "id") @QueryInit("*.*") private User reviewer; - - @ManyToOne(optional=false) - @QueryInit({"headSupervisor", "projectType"}) - private Project project; - - @ManyToOne(optional=false) - @QueryInit({"project.headSupervisor","requester.user", "language", "checklistTemplate"}) - private PeerRequest peerRequest; - + + // ---------------------------------------------------------------------------------- + // JPA-mappings of other tables referencing to this table "peer_review" + // ---------------------------------------------------------------------------------- @OneToMany(mappedBy="peerReview", orphanRemoval=true, cascade=CascadeType.ALL) @OrderBy("id") private List<Answer> answers = new ArrayList<>(); - @OneToOne(optional=true, orphanRemoval = true, cascade = CascadeType.ALL) - @JoinColumn(name = "file_reference_id") - private FileReference file; - - @Lob - private String comment; + // ---------------------------------------------------------------------------------- + // getters and setters + // ---------------------------------------------------------------------------------- + @Override + public Long getId() { + return this.id; + } - @Enumerated(EnumType.STRING) - private ReviewStatus status = ReviewStatus.IN_PROGRESS; + public void setId(Long id) { + this.id = id; + } - @Basic(optional = false) - private Date deadline; + public String getComment() { + return this.comment; + } - @Override + public void setComment(String comment) { + this.comment = comment; + } + + public ReviewStatus getStatus() { + return status; + } + + public void setStatus(ReviewStatus status) { + this.status = status; + } + + public Date getDeadline() { + return this.deadline; + } + + public void setDeadline(Date deadline) { + this.deadline = deadline; + } + + public FileReference getFile() { + return this.file; + } + + public void setFile(FileReference file) { + this.file = file; + } + + public PeerRequest getPeerRequest() { + return this.peerRequest; + } + + public void setPeerRequest(PeerRequest peerRequest) { + this.peerRequest = peerRequest; + } + + public Project getProject() { + return this.project; + } + + public void setProject(Project project) { + this.project = project; + } + + public User getReviewer() { + return this.reviewer; + } + + public void setReviewer(User reviewer) { + this.reviewer = reviewer; + } + + public List<Answer> getAnswers() { + return this.answers; + } + + public void setAnswers(List<Answer> answers) { + this.answers = answers; + } + + public void addAnswer(String question) { + this.answers.add(new Answer(this, question)); + } + + // ---------------------------------------------------------------------------------- + // other methods + // ---------------------------------------------------------------------------------- + @Override public final String getCommentKey() { return PeerReview.class.getCanonicalName(); } @@ -73,10 +189,6 @@ public class PeerReview extends DomainObject implements Commentable { return new Date().after(getDeadline()); } - public ReviewStatus getStatus() { - return status; - } - public boolean isExpired() { return status == ReviewStatus.EXPIRED; } @@ -97,90 +209,12 @@ public class PeerReview extends DomainObject implements Commentable { setStatus(isLate() ? ReviewStatus.EXPIRED : ReviewStatus.COMPLETED); } - private static boolean isEmpty(String s) { - return s == null || s.isBlank(); - } - public void expire() { status = ReviewStatus.EXPIRED; } - public void addAnswer(String question) { - this.answers.add(new Answer(this, question)); - } - - @Override - public Long getId() { - return this.id; - } - - public User getReviewer() { - return this.reviewer; - } - - public Project getProject() { - return this.project; - } - - public PeerRequest getPeerRequest() { - return this.peerRequest; - } - - public List<Answer> getAnswers() { - return this.answers; - } - - public FileReference getFile() { - return this.file; - } - - public String getComment() { - return this.comment; - } - - public Date getDeadline() { - return this.deadline; - } - - public void setId(Long id) { - this.id = id; - } - - public void setReviewer(User reviewer) { - this.reviewer = reviewer; - } - - public void setProject(Project project) { - this.project = project; - } - - public void setPeerRequest(PeerRequest peerRequest) { - this.peerRequest = peerRequest; - } - - public void setAnswers(List<Answer> answers) { - this.answers = answers; - } - - public void setFile(FileReference file) { - this.file = file; - } - - public void setComment(String comment) { - this.comment = comment; - } - - public void setStatus(ReviewStatus status) { - this.status = status; - } - - public void setDeadline(Date deadline) { - this.deadline = deadline; - } - - @Override - public String toString() { - return "PeerReview(id=" + this.getId() + ", reviewer=" + this.getReviewer() + ", project=" + this.getProject() + ", peerRequest=" + this.getPeerRequest() + ", answers=" + this.getAnswers() + ", file=" + this.getFile() + ", comment=" + this.getComment() + ", status=" + this.getStatus() + ", deadline=" + this.getDeadline() + ")"; + protected boolean canEqual(final Object other) { + return other instanceof PeerReview; } @Override @@ -192,12 +226,23 @@ public class PeerReview extends DomainObject implements Commentable { && Objects.equals(this.getId(), other.getId()); } - protected boolean canEqual(final Object other) { - return other instanceof PeerReview; + @Override + public int hashCode() { + return Objects.hashCode(this.getId()); } @Override - public int hashCode() { - return Objects.hashCode(this.getId()); + public String toString() { + return "PeerReview(id=" + this.getId() + ", reviewer=" + this.getReviewer() + ", project=" + + this.getProject() + ", peerRequest=" + this.getPeerRequest() + ", answers=" + this.getAnswers() + + ", file=" + this.getFile() + ", comment=" + this.getComment() + ", status=" + this.getStatus() + + ", deadline=" + this.getDeadline() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Static helper methods + // ---------------------------------------------------------------------------------- + private static boolean isEmpty(String s) { + return s == null || s.isBlank(); } } diff --git a/core/src/main/java/se/su/dsv/scipro/plagiarism/PlagiarismRequest.java b/core/src/main/java/se/su/dsv/scipro/plagiarism/PlagiarismRequest.java index 3356526223..1aece5bd51 100644 --- a/core/src/main/java/se/su/dsv/scipro/plagiarism/PlagiarismRequest.java +++ b/core/src/main/java/se/su/dsv/scipro/plagiarism/PlagiarismRequest.java @@ -11,46 +11,61 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToOne; import jakarta.persistence.Table; -import java.util.*; + +import java.util.Objects; @Entity @Table(name = "plagiarism_request") class PlagiarismRequest { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (plagiarism_request) referencing other + // tables. + // ---------------------------------------------------------------------------------- @OneToOne(optional = false) - @JoinColumn(name = "document_reference_id") + @JoinColumn(name = "document_file_reference_id", referencedColumnName = "id") private FileReference document; @ManyToOne + @JoinColumn(name = "receiver_user_id", referencedColumnName = "id") private User receiver; + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public Long getId() { return this.id; } - public FileReference getDocument() { - return this.document; - } - - public User getReceiver() { - return this.receiver; - } - public void setId(Long id) { this.id = id; } + public FileReference getDocument() { + return this.document; + } + public void setDocument(FileReference fileDescription) { this.document = fileDescription; } + public User getReceiver() { + return this.receiver; + } + public void setReceiver(User receiver) { this.receiver = receiver; } + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -62,10 +77,6 @@ class PlagiarismRequest { && Objects.equals(this.getReceiver(), other.getReceiver()); } - protected boolean canEqual(final Object other) { - return other instanceof PlagiarismRequest; - } - @Override public int hashCode() { return Objects.hash(this.getId(), this.getDocument(), this.getReceiver()); @@ -73,6 +84,14 @@ class PlagiarismRequest { @Override public String toString() { - return "PlagiarismRequest(id=" + this.getId() + ", fileDescription=" + this.getDocument() + ", receiver=" + this.getReceiver() + ")"; + return "PlagiarismRequest(id=" + this.getId() + ", fileDescription=" + this.getDocument() + + ", receiver=" + this.getReceiver() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other method + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof PlagiarismRequest; } } diff --git a/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundSettings.java b/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundSettings.java index 74716b4e56..fa97b51a46 100644 --- a/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundSettings.java +++ b/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundSettings.java @@ -1,9 +1,11 @@ package se.su.dsv.scipro.plagiarism.urkund; import jakarta.persistence.Basic; +import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; + import java.util.Objects; @Entity @@ -15,12 +17,15 @@ public class UrkundSettings { private long id = ID; @Basic + @Column(name = "enabled") private boolean enabled = false; @Basic + @Column(name = "username") private String username; @Basic + @Column(name = "password") private String password; public boolean isEnabled() { @@ -70,6 +75,7 @@ public class UrkundSettings { @Override public String toString() { - return "UrkundSettings(id=" + this.id + ", enabled=" + this.isEnabled() + ", username=" + this.getUsername() + ", password=" + this.getPassword() + ")"; + return "UrkundSettings(id=" + this.id + ", enabled=" + this.isEnabled() + ", username=" + + this.getUsername() + ", password=" + this.getPassword() + ")"; } } diff --git a/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundSubmission.java b/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundSubmission.java index 594dd691fc..87580259a7 100644 --- a/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundSubmission.java +++ b/core/src/main/java/se/su/dsv/scipro/plagiarism/urkund/UrkundSubmission.java @@ -17,139 +17,159 @@ import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToOne; import jakarta.persistence.Table; import java.time.Instant; -import java.util.*; +import java.util.Objects; @Entity @Table(name = "urkund_submission") public class UrkundSubmission extends DomainObject { - - public enum State { - SUBMISSION_FAILED, SUBMITTED, REJECTED, ACCEPTED, ANALYZED, ERROR; - - public boolean isFinal() { - return !(this == SUBMITTED || this == ACCEPTED); - } - } - + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @ManyToOne - private User receiver; + @Basic + @Column(name = "submitted_date", nullable = false) + private Instant submitted; @Basic - private String analysisAddress; - - @Column(nullable = false) + @Column(name = "state", nullable = false) @Enumerated(EnumType.STRING) private State state; - @Column(nullable = false) - private Instant submitted; - - @Column(nullable = false) + @Basic + @Column(name = "next_poll_date", nullable = false) private Instant nextPoll; - @Column(nullable = false) + @Basic + @Column(name = "polling_delay", nullable = false) @Enumerated(EnumType.STRING) private PollingDelay pollingDelay = PollingDelay.FIRST; - @OneToOne(optional = false) - @JoinColumn(name = "document_reference_id") - private FileReference document; - @Basic(optional = false) + @Column(name = "message") private String message; @Basic + @Column(name = "report_url") private String reportUrl; @Basic + @Column(name = "significance") private Float significance; + @Basic + @Column(name = "analysis_address") + private String analysisAddress; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (urkund_submission) referencing other + // tables. + // ---------------------------------------------------------------------------------- + @OneToOne(optional = false) + @JoinColumn(name = "document_file_reference_id", referencedColumnName = "id") + private FileReference document; + + @ManyToOne + @JoinColumn(name = "receiver_user_id", referencedColumnName = "id") + private User receiver; + + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- @Override public Long getId() { return this.id; } - public String getAnalysisAddress() { - return this.analysisAddress; - } - - public State getState() { - return this.state; - } - - public Instant getSubmitted() { - return this.submitted; - } - - public FileReference getDocument() { - return this.document; - } - - public String getMessage() { - return this.message; - } - - public String getReportUrl() { - return this.reportUrl; - } - - public Float getSignificance() { - return this.significance; - } - - @Override - public String toString() { - return "UrkundSubmission(id=" + this.getId() + ", receiver=" + this.getReceiver() + ", analysisAddress=" + this.getAnalysisAddress() + ", state=" + this.getState() + ", submitted=" + this.getSubmitted() + ", nextPoll=" + this.getNextPoll() + ", pollingDelay=" + this.getPollingDelay() + ", fileDescription=" + this.getDocument() + ", message=" + this.getMessage() + ", reportUrl=" + this.getReportUrl() + ", significance=" + this.getSignificance() + ")"; - } - void setId(Long id) { this.id = id; } - void setReceiver(User receiver) { - this.receiver = receiver; - } - - void setAnalysisAddress(String analysisAddress) { - this.analysisAddress = analysisAddress; - } - - void setState(State state) { - this.state = state; + public Instant getSubmitted() { + return this.submitted; } void setSubmitted(Instant submitted) { this.submitted = submitted; } + public State getState() { + return this.state; + } + + void setState(State state) { + this.state = state; + } + + Instant getNextPoll() { + return this.nextPoll; + } + void setNextPoll(Instant nextPoll) { this.nextPoll = nextPoll; } + PollingDelay getPollingDelay() { + return this.pollingDelay; + } + void setPollingDelay(PollingDelay pollingDelay) { this.pollingDelay = pollingDelay; } - void setDocument(FileReference fileDescription) { - this.document = fileDescription; + public String getMessage() { + return this.message; } void setMessage(String message) { this.message = message; } + public String getReportUrl() { + return this.reportUrl; + } + void setReportUrl(String reportUrl) { this.reportUrl = reportUrl; } + public Float getSignificance() { + return this.significance; + } + void setSignificance(Float significance) { this.significance = significance; } + public String getAnalysisAddress() { + return this.analysisAddress; + } + + void setAnalysisAddress(String analysisAddress) { + this.analysisAddress = analysisAddress; + } + + public FileReference getDocument() { + return this.document; + } + + void setDocument(FileReference fileDescription) { + this.document = fileDescription; + } + + User getReceiver() { + return this.receiver; + } + + void setReceiver(User receiver) { + this.receiver = receiver; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -170,10 +190,6 @@ public class UrkundSubmission extends DomainObject { && Objects.equals(this.getSignificance(), other.getSignificance()); } - protected boolean canEqual(final Object other) { - return other instanceof UrkundSubmission; - } - @Override public int hashCode() { return Objects.hash( @@ -190,15 +206,31 @@ public class UrkundSubmission extends DomainObject { this.getSignificance()); } - User getReceiver() { - return this.receiver; + @Override + public String toString() { + return "UrkundSubmission(id=" + this.getId() + ", receiver=" + this.getReceiver() + + ", analysisAddress=" + this.getAnalysisAddress() + ", state=" + + this.getState() + ", submitted=" + this.getSubmitted() + + ", nextPoll=" + this.getNextPoll() + ", pollingDelay=" + this.getPollingDelay() + + ", fileDescription=" + this.getDocument() + ", message=" + this.getMessage() + + ", reportUrl=" + this.getReportUrl() + ", significance=" + this.getSignificance() + ")"; } - Instant getNextPoll() { - return this.nextPoll; + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof UrkundSubmission; } - PollingDelay getPollingDelay() { - return this.pollingDelay; + // ---------------------------------------------------------------------------------- + // Nested type + // ---------------------------------------------------------------------------------- + public enum State { + SUBMISSION_FAILED, SUBMITTED, REJECTED, ACCEPTED, ANALYZED, ERROR; + + public boolean isFinal() { + return !(this == SUBMITTED || this == ACCEPTED); + } } } diff --git a/core/src/main/java/se/su/dsv/scipro/project/Author.java b/core/src/main/java/se/su/dsv/scipro/project/Author.java index c3094e697c..8adaa5fed3 100644 --- a/core/src/main/java/se/su/dsv/scipro/project/Author.java +++ b/core/src/main/java/se/su/dsv/scipro/project/Author.java @@ -1,26 +1,34 @@ package se.su.dsv.scipro.project; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import jakarta.persistence.EmbeddedId; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.MapsId; +import jakarta.persistence.Table; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.io.Serializable; import java.util.Objects; @Entity @Table(name = "project_user") public class Author { + // ---------------------------------------------------------------------------------- + // Embedded JPA-mapping + // ---------------------------------------------------------------------------------- @EmbeddedId private AuthorPK authorPK; - @ManyToOne(optional = false) - @JoinColumn(name = "project_id", nullable = false) - @MapsId("projectId") - private Project project; - - @ManyToOne(optional = false) - @JoinColumn(name = "user_id", nullable = false) - @MapsId("userId") - private User user; + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- + @Basic(optional = true) + @Column(name = "reflection") + private String reflection; /** * If this author wants to be notified when a final seminar created @@ -36,15 +44,29 @@ public class Author { @Column(name = "subscribed_to_final_seminar_notifications", nullable = false, columnDefinition = "BOOLEAN DEFAULT FALSE") private boolean subscribedToFinalSeminarNotifications; - @Basic(optional = true) - private String reflection; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (project_user) referencing other + // tables. + // ---------------------------------------------------------------------------------- + @ManyToOne(optional = false) + @JoinColumn(name = "project_id", nullable = false) + @MapsId("projectId") + private Project project; - public Project getProject() { - return project; + @ManyToOne(optional = false) + @JoinColumn(name = "user_id", nullable = false) + @MapsId("userId") + private User user; + + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- + public String getReflection() { + return reflection; } - public User getUser() { - return user; + public void setReflection(String reflection) { + this.reflection = reflection; } public boolean isSubscribedToFinalSeminarNotifications() { @@ -55,14 +77,17 @@ public class Author { this.subscribedToFinalSeminarNotifications = subscribedToFinalSeminarNotifications; } - public String getReflection() { - return reflection; + public Project getProject() { + return project; } - public void setReflection(String reflection) { - this.reflection = reflection; + public User getUser() { + return user; } + // ---------------------------------------------------------------------------------- + // Nested class + // ---------------------------------------------------------------------------------- @Embeddable public static class AuthorPK implements Serializable { private Long projectId; diff --git a/core/src/main/java/se/su/dsv/scipro/project/Project.java b/core/src/main/java/se/su/dsv/scipro/project/Project.java index 9429d2cbfc..569d1da4a7 100755 --- a/core/src/main/java/se/su/dsv/scipro/project/Project.java +++ b/core/src/main/java/se/su/dsv/scipro/project/Project.java @@ -1,13 +1,51 @@ package se.su.dsv.scipro.project; import com.querydsl.core.annotations.QueryInit; +import jakarta.persistence.AttributeOverride; +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.MapKeyJoinColumn; +import jakarta.persistence.PrePersist; +import jakarta.persistence.PreUpdate; +import jakarta.persistence.Table; + import se.su.dsv.scipro.data.dataobjects.Member; import se.su.dsv.scipro.reusable.SciProUtilities; -import se.su.dsv.scipro.system.*; +import se.su.dsv.scipro.system.DegreeType; +import se.su.dsv.scipro.system.DomainObject; +import se.su.dsv.scipro.system.Language; +import se.su.dsv.scipro.system.ProjectModule; +import se.su.dsv.scipro.system.ProjectType; +import se.su.dsv.scipro.system.ResearchArea; +import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.time.LocalDate; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.stream.Collectors; @Entity @@ -18,17 +56,30 @@ public class Project extends DomainObject { public static final String NO_CO_SUPERVISOR = "No co-supervisor"; public static final int TITLE_MAX_LENGTH = 255; + public static ITitle builder() { + return new Builder(); + } + + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(unique = true) - private Integer identifier; - - @Column(length = TITLE_MAX_LENGTH) @Basic(optional = false) + @Column(name = "title", length = TITLE_MAX_LENGTH) private String title; + @Basic + @Column(name = "credits") + private int credits; + + @Basic + @Column(name = "language") + @Enumerated(EnumType.STRING) + private Language language; + @Basic(optional = false) @Column(name = "start_date", nullable = false) private LocalDate startDate; @@ -37,61 +88,91 @@ public class Project extends DomainObject { @Column(name = "expected_end_date") private LocalDate expectedEndDate; - @ManyToMany - @JoinTable(name = "project_user", inverseJoinColumns = @JoinColumn(name = "user_id")) - private Set<User> projectParticipants = new TreeSet<>(new User.ByNameComparator()); - - @ManyToMany - @JoinTable(name = "project_reviewer", inverseJoinColumns = @JoinColumn(name = "user_id")) - private Set<User> reviewers = new TreeSet<>(new User.ByNameComparator()); - - @ManyToMany - @JoinTable(name = "project_cosupervisor", inverseJoinColumns = @JoinColumn(name = "user_id")) - private Set<User> coSupervisors = new TreeSet<>(new User.ByNameComparator()); - - @ManyToOne(optional = false) - @QueryInit({"unit"}) - @JoinColumn(name = "supervisor_id") - private User headSupervisor; - + @Basic + @Column(name = "project_status") @Enumerated(EnumType.STRING) private ProjectStatus projectStatus = ProjectStatus.ACTIVE; + @Basic + @Column(name = "final_seminar_rule_exmpt") + private boolean finalSeminarRuleExempted = false; + + @Basic + @Column(name = "state_of_mind") @Enumerated(EnumType.STRING) private StateOfMind stateOfMind = StateOfMind.FINE; @Basic(optional = true) - private Date stateOfMindDate; - - @Basic(optional = true) + @Column(name = "state_of_mind_reason") private String stateOfMindReason; - @ManyToOne(optional = false) - private ProjectType projectType; - - @Embedded - @AttributeOverride(name = "name", column = @Column(name = "externalOrganization")) - private ExternalOrganization externalOrganization; - - @Column(name = "fs_rule_exmpt") - private boolean finalSeminarRuleExempted = false; + @Basic(optional = true) + @Column(name = "state_of_mind_date") + private Date stateOfMindDate; @Basic - private int credits; + @Column(name = "daisy_identifier", unique = true) + private Integer identifier; + + // ---------------------------------------------------------------------------------- + // Embedded JPA-mapping + // ---------------------------------------------------------------------------------- + @Embedded + @AttributeOverride(name = "name", column = @Column(name = "external_organization")) + private ExternalOrganization externalOrganization; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (opposition_report) referencing other + // tables. + // ---------------------------------------------------------------------------------- + @ManyToOne(optional = false) + @JoinColumn(name = "project_type_id", referencedColumnName = "id") + private ProjectType projectType; @ManyToOne(optional = true) + @JoinColumn(name = "research_area_id", referencedColumnName = "id") private ResearchArea researchArea; - @Enumerated(EnumType.STRING) - private Language language; + @ManyToOne(optional = false) + @JoinColumn(name = "supervisor_id", referencedColumnName = "id") + @QueryInit({"unit"}) + private User headSupervisor; + // ---------------------------------------------------------------------------------- + // @ManyToMany JPA-mappings + // ---------------------------------------------------------------------------------- + @ManyToMany + @JoinTable(name = "project_user", + joinColumns = @JoinColumn(name = "project_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id")) + private Set<User> projectParticipants = new TreeSet<>(new User.ByNameComparator()); + + @ManyToMany + @JoinTable(name = "project_reviewer", + joinColumns = @JoinColumn(name = "project_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id")) + private Set<User> reviewers = new TreeSet<>(new User.ByNameComparator()); + + @ManyToMany + @JoinTable(name = "project_cosupervisor", + joinColumns = @JoinColumn(name = "project_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id")) + private Set<User> coSupervisors = new TreeSet<>(new User.ByNameComparator()); + + // ---------------------------------------------------------------------------------- + // JPA-mappings of other tables referencing to this table "project" + // ---------------------------------------------------------------------------------- @ElementCollection(fetch = FetchType.LAZY) - @CollectionTable(name = "project_user_note", joinColumns = @JoinColumn(name = "project_id")) + @CollectionTable(name = "project_user_note", + joinColumns = @JoinColumn(name = "project_id", referencedColumnName = "id")) @Column(name = "note") @SuppressWarnings("JpaDataSourceORMInspection") // false warning from IntelliJ for the @MapKeyJoinColumn @MapKeyJoinColumn(name = "user_id") private Map<User, String> userNotes = new HashMap<>(); + // ---------------------------------------------------------------------------------- + // JPA Lifecycle Methods + // ---------------------------------------------------------------------------------- @PrePersist @PreUpdate void cleanTitle() { @@ -101,12 +182,67 @@ public class Project extends DomainObject { title = title.trim(); } - public Map<User, String> getUserNotes() { - return userNotes; + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- + @Override + public Long getId() { + return this.id; } - public void setUserNotes(Map<User, String> userNotes) { - this.userNotes = userNotes; + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return SciProUtilities.cleanString(title); + } + + public void setTitle(String title) { + this.title = title; + } + + public int getCredits() { + return this.credits; + } + + public void setCredits(int credits) { + this.credits = credits; + } + + public Language getLanguage() { + return this.language; + } + + public void setLanguage(Language language) { + this.language = language; + } + + public LocalDate getStartDate() { + return startDate; + } + + public void setStartDate(LocalDate startDate) { + this.startDate = startDate; + } + + public LocalDate getExpectedEndDate() { + return this.expectedEndDate; + } + + public void setExpectedEndDate(LocalDate expectedEndDate) { + this.expectedEndDate = expectedEndDate; + } + + public ProjectStatus getProjectStatus() { + return this.projectStatus; + } + + public void setProjectStatus(ProjectStatus projectStatus) { + this.projectStatus = projectStatus; + if (projectStatus == ProjectStatus.COMPLETED) { + this.stateOfMind = StateOfMind.FINE; + } } public boolean isFinalSeminarRuleExempted() { @@ -117,53 +253,20 @@ public class Project extends DomainObject { this.finalSeminarRuleExempted = finalSeminarRuleExempted; } - public User getHeadSupervisor() { - return headSupervisor; + public StateOfMind getStateOfMind() { + return this.stateOfMind; } - public ProjectType getProjectType() { - return projectType; + public void setStateOfMind(StateOfMind stateOfMind) { + this.stateOfMind = stateOfMind; } - public SortedSet<User> getCoSupervisors() { - TreeSet<User> s = new TreeSet<>(new User.ByNameComparator()); - s.addAll(coSupervisors); - return Collections.unmodifiableSortedSet(s); + public String getStateOfMindReason() { + return this.stateOfMindReason; } - public void setCoSupervisors(Collection<User> coSupervisors) { - this.coSupervisors.clear(); - this.coSupervisors.addAll(coSupervisors); - } - - public void addCoSupervisor(User coSupervisor) { - coSupervisors.add(coSupervisor); - } - - public SortedSet<User> getReviewers() { - TreeSet<User> s = new TreeSet<>(new User.ByNameComparator()); - s.addAll(reviewers); - return Collections.unmodifiableSortedSet(s); - } - - public void setReviewers(Collection<User> reviewers) { - this.reviewers.clear(); - this.reviewers.addAll(reviewers); - } - - public void addReviewer(User reviewer) { - reviewers.add(reviewer); - } - - public void removeReviewer(User reviewer) { - reviewers.remove(reviewer); - } - - public void setProjectStatus(ProjectStatus projectStatus) { - this.projectStatus = projectStatus; - if (projectStatus == ProjectStatus.COMPLETED) { - this.stateOfMind = StateOfMind.FINE; - } + public void setStateOfMindReason(String stateOfMindReason) { + this.stateOfMindReason = stateOfMindReason; } public Date getStateOfMindDate() { @@ -176,8 +279,44 @@ public class Project extends DomainObject { : new Date(stateOfMindDate.getTime()); } - public String getTitle() { - return SciProUtilities.cleanString(title); + public Integer getIdentifier() { + return this.identifier; + } + + public void setIdentifier(Integer identifier) { + this.identifier = identifier; + } + + public ExternalOrganization getExternalOrganization() { + return this.externalOrganization; + } + + public void setExternalOrganization(ExternalOrganization externalOrganization) { + this.externalOrganization = externalOrganization; + } + + public ProjectType getProjectType() { + return projectType; + } + + public void setProjectType(ProjectType projectType) { + this.projectType = projectType; + } + + public ResearchArea getResearchArea() { + return this.researchArea; + } + + public void setResearchArea(ResearchArea researchArea) { + this.researchArea = researchArea; + } + + public User getHeadSupervisor() { + return headSupervisor; + } + + public void setHeadSupervisor(User headSupervisor) { + this.headSupervisor = headSupervisor; } public SortedSet<User> getProjectParticipants() { @@ -191,11 +330,91 @@ public class Project extends DomainObject { this.projectParticipants.addAll(projectParticipants); } + public SortedSet<User> getReviewers() { + TreeSet<User> s = new TreeSet<>(new User.ByNameComparator()); + s.addAll(reviewers); + return Collections.unmodifiableSortedSet(s); + } + + public void setReviewers(Collection<User> reviewers) { + this.reviewers.clear(); + this.reviewers.addAll(reviewers); + } + + public SortedSet<User> getCoSupervisors() { + TreeSet<User> s = new TreeSet<>(new User.ByNameComparator()); + s.addAll(coSupervisors); + return Collections.unmodifiableSortedSet(s); + } + + public void setCoSupervisors(Collection<User> coSupervisors) { + this.coSupervisors.clear(); + this.coSupervisors.addAll(coSupervisors); + } + + public Map<User, String> getUserNotes() { + return userNotes; + } + + public void setUserNotes(Map<User, String> userNotes) { + this.userNotes = userNotes; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- + @Override + public boolean equals(final Object o) { + if (o == this) return true; + if (!(o instanceof Project)) return false; + final Project other = (Project) o; + return other.canEqual(this) + && Objects.equals(this.getId(), other.getId()); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.getId()); + } + + @Override + public String toString() { + return "Project(id=" + this.getId() + ", identifier=" + this.getIdentifier() + + ", title=" + this.getTitle() + ", projectParticipants=" + this.getProjectParticipants() + + ", headSupervisor=" + this.getHeadSupervisor() + ", projectType=" + + this.getProjectType() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- + + protected boolean canEqual(final Object other) { + return other instanceof Project; + } + public void addProjectParticipant(User s) { projectParticipants.add(s); } - //TODO remove this method + public boolean isParticipant(User user) { + for (User s : projectParticipants) { + if (s.equals(user)) { + return true; + } + } + return false; + } + + public void addReviewer(User reviewer) { + reviewers.add(reviewer); + } + + public void removeReviewer(User reviewer) { + reviewers.remove(reviewer); + } + + // TODO remove this method public User getReviewer() { if (reviewers.isEmpty()) { return null; @@ -204,6 +423,14 @@ public class Project extends DomainObject { } } + public String getReviewerName() { + return getReviewer() != null ? getReviewer().getFullName() : NO_REVIEWER; + } + + public void addCoSupervisor(User coSupervisor) { + coSupervisors.add(coSupervisor); + } + public List<Member> getMembers() { List<Member> members = new ArrayList<>(); @@ -240,23 +467,10 @@ public class Project extends DomainObject { return externalOrganization != null; } - public boolean isParticipant(User user) { - for (User s : projectParticipants) { - if (s.equals(user)) { - return true; - } - } - return false; - } - public String getSupervisorName() { return getHeadSupervisor().getFullName(); } - public String getReviewerName() { - return getReviewer() != null ? getReviewer().getFullName() : NO_REVIEWER; - } - public DegreeType getProjectTypeDegreeType() { return getProjectType().getDegreeType(); } @@ -289,10 +503,6 @@ public class Project extends DomainObject { return getProjectType().hasModule(projectModule); } - public static ITitle builder() { - return new Builder(); - } - public boolean isSupervisor(User user) { return headSupervisor != null && headSupervisor.equals(user); } @@ -319,125 +529,9 @@ public class Project extends DomainObject { return Objects.requireNonNullElse(language, getProjectType().getDefaultLanguage()); } - @Override - public Long getId() { - return this.id; - } - - public Integer getIdentifier() { - return this.identifier; - } - - public LocalDate getExpectedEndDate() { - return this.expectedEndDate; - } - - public ProjectStatus getProjectStatus() { - return this.projectStatus; - } - - public StateOfMind getStateOfMind() { - return this.stateOfMind; - } - - public String getStateOfMindReason() { - return this.stateOfMindReason; - } - - public ExternalOrganization getExternalOrganization() { - return this.externalOrganization; - } - - public int getCredits() { - return this.credits; - } - - public ResearchArea getResearchArea() { - return this.researchArea; - } - - public Language getLanguage() { - return this.language; - } - - public void setId(Long id) { - this.id = id; - } - - public void setIdentifier(Integer identifier) { - this.identifier = identifier; - } - - public void setTitle(String title) { - this.title = title; - } - - public void setExpectedEndDate(LocalDate expectedEndDate) { - this.expectedEndDate = expectedEndDate; - } - - public void setHeadSupervisor(User headSupervisor) { - this.headSupervisor = headSupervisor; - } - - public void setStateOfMind(StateOfMind stateOfMind) { - this.stateOfMind = stateOfMind; - } - - public void setStateOfMindReason(String stateOfMindReason) { - this.stateOfMindReason = stateOfMindReason; - } - - public void setProjectType(ProjectType projectType) { - this.projectType = projectType; - } - - public void setExternalOrganization(ExternalOrganization externalOrganization) { - this.externalOrganization = externalOrganization; - } - - public void setCredits(int credits) { - this.credits = credits; - } - - public void setResearchArea(ResearchArea researchArea) { - this.researchArea = researchArea; - } - - public void setLanguage(Language language) { - this.language = language; - } - - public LocalDate getStartDate() { - return startDate; - } - - public void setStartDate(LocalDate startDate) { - this.startDate = startDate; - } - - @Override - public boolean equals(final Object o) { - if (o == this) return true; - if (!(o instanceof Project)) return false; - final Project other = (Project) o; - return other.canEqual(this) - && Objects.equals(this.getId(), other.getId()); - } - - protected boolean canEqual(final Object other) { - return other instanceof Project; - } - - @Override - public int hashCode() { - return Objects.hashCode(this.getId()); - } - - @Override - public String toString() { - return "Project(id=" + this.getId() + ", identifier=" + this.getIdentifier() + ", title=" + this.getTitle() + ", projectParticipants=" + this.getProjectParticipants() + ", headSupervisor=" + this.getHeadSupervisor() + ", projectType=" + this.getProjectType() + ")"; - } + // ---------------------------------------------------------------------------------- + // Nested classes and interfaces + // ---------------------------------------------------------------------------------- private static class Builder implements ITitle, IProjectType, IStartDate, IBuild { private final Project instance = new Project(); diff --git a/core/src/main/java/se/su/dsv/scipro/projectpartner/ProjectPartner.java b/core/src/main/java/se/su/dsv/scipro/projectpartner/ProjectPartner.java index 0afe97861e..643956fe8e 100755 --- a/core/src/main/java/se/su/dsv/scipro/projectpartner/ProjectPartner.java +++ b/core/src/main/java/se/su/dsv/scipro/projectpartner/ProjectPartner.java @@ -1,15 +1,26 @@ package se.su.dsv.scipro.projectpartner; +import java.util.Objects; + +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Lob; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; + import se.su.dsv.scipro.match.ApplicationPeriod; import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.ProjectType; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; -import java.util.Objects; - @Entity -@Table(name="projectPartner") +@Table(name="project_partner") @Cacheable(true) public class ProjectPartner extends DomainObject { @Id @@ -20,17 +31,19 @@ public class ProjectPartner extends DomainObject { private User user; @ManyToOne(optional = false) + @JoinColumn(name = "project_type_id") private ProjectType projectType; @ManyToOne(optional = false) + @JoinColumn(name = "application_period_id") private ApplicationPeriod applicationPeriod; @Lob - @Basic(optional=false) + @Column(name = "info_text", nullable=false) private String infotext; @Basic(optional = false) - @Column(nullable = false, name = "active") + @Column(name = "active", nullable = false) private boolean active = true; public ProjectPartner(User user){ diff --git a/core/src/main/java/se/su/dsv/scipro/report/AbstractCriterion.java b/core/src/main/java/se/su/dsv/scipro/report/AbstractCriterion.java index 7fd640236b..e9d80f2699 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/AbstractCriterion.java +++ b/core/src/main/java/se/su/dsv/scipro/report/AbstractCriterion.java @@ -1,12 +1,12 @@ package se.su.dsv.scipro.report; -import jakarta.persistence.GenerationType; -import se.su.dsv.scipro.system.DomainObject; - import jakarta.persistence.Basic; +import jakarta.persistence.Column; import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.MappedSuperclass; +import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.Language; import java.io.Serializable; @@ -15,19 +15,28 @@ import java.util.Objects; @MappedSuperclass public abstract class AbstractCriterion extends DomainObject { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Basic(optional = false) + @Basic + @Column(name = "title_sv", nullable = false) private String title; - @Basic(optional = false) + @Basic + @Column(name = "title_en", nullable = false) private String titleEn; - @Basic(optional = false) + @Basic + @Column(name = "sort_order", nullable = false) private Integer sortOrder; + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- protected AbstractCriterion() { } @@ -37,6 +46,9 @@ public abstract class AbstractCriterion extends DomainObject { this.sortOrder = sortOrder; } + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- @Override public Long getId() { return this.id; @@ -50,14 +62,13 @@ public abstract class AbstractCriterion extends DomainObject { return titleEn; } - public String getTitle(Language language) { - return language == Language.ENGLISH ? getTitleEn() : getTitle(); - } - public Integer getSortOrder() { return this.sortOrder; } + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -71,10 +82,6 @@ public abstract class AbstractCriterion extends DomainObject { && Objects.equals(this.getSortOrder(), other.getSortOrder()); } - protected boolean canEqual(final Object other) { - return other instanceof AbstractCriterion; - } - @Override public int hashCode() { return Objects.hash(this.getId(), this.getTitle(), this.getTitleEn(), this.getSortOrder()); @@ -85,6 +92,20 @@ public abstract class AbstractCriterion extends DomainObject { return "AbstractCriterion(id=" + this.getId() + ", title=" + this.getTitle() + ", titleEn=" + this.getTitleEn() + ", sortOrder=" + this.getSortOrder() + ")"; } + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof AbstractCriterion; + } + + public String getTitle(Language language) { + return language == Language.ENGLISH ? getTitleEn() : getTitle(); + } + + // ---------------------------------------------------------------------------------- + // Embedded class + // ---------------------------------------------------------------------------------- public static class BySortOrderComparator implements Comparator<AbstractCriterion>, Serializable { @Override public int compare(AbstractCriterion o1, AbstractCriterion o2) { diff --git a/core/src/main/java/se/su/dsv/scipro/report/AbstractGradingCriterion.java b/core/src/main/java/se/su/dsv/scipro/report/AbstractGradingCriterion.java index 64d2f0433b..81b55d0982 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/AbstractGradingCriterion.java +++ b/core/src/main/java/se/su/dsv/scipro/report/AbstractGradingCriterion.java @@ -8,7 +8,109 @@ import jakarta.persistence.MappedSuperclass; @MappedSuperclass public abstract class AbstractGradingCriterion extends AbstractCriterion { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- + @Basic(optional = false) + @Column(name = "points_required_to_pass", nullable = false) + protected int pointsRequiredToPass; + @Basic + @Column(name = "fx") + private boolean fx = true; + + @Basic + @Column(name = "flag") + @Enumerated(EnumType.STRING) + private Flag flag; + + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- + protected AbstractGradingCriterion() { + + } + + protected AbstractGradingCriterion(String title, String titleEn, int sortOrder, int pointsRequiredToPass) { + super(title, titleEn, sortOrder); + this.pointsRequiredToPass = pointsRequiredToPass; + } + + protected AbstractGradingCriterion(String title, String titleEn, Integer sortOrder, int pointsRequiredToPass, + Flag flag) { + this(title, titleEn, sortOrder, pointsRequiredToPass); + this.flag = flag; + } + + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- + public int getPointsRequiredToPass() { + return this.pointsRequiredToPass; + } + + public boolean isFx() { + return this.fx; + } + + public void setFx(boolean fx) { + this.fx = fx; + } + + public Flag getFlag() { + return flag; + } + + public void setFlag(Flag flag) { + this.flag = flag; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- + @Override + public boolean equals(final Object o) { + if (o == this) return true; + if (!(o instanceof AbstractGradingCriterion)) return false; + final AbstractGradingCriterion other = (AbstractGradingCriterion) o; + return other.canEqual(this) + && super.equals(o) + && this.getPointsRequiredToPass() == other.getPointsRequiredToPass() + && this.isFx() == other.isFx(); + } + + @Override + public int hashCode() { + final int PRIME = 59; + int result = super.hashCode(); + result = result * PRIME + this.getPointsRequiredToPass(); + result = result * PRIME + (this.isFx() ? 79 : 97); + return result; + } + + @Override + public String toString() { + return "AbstractGradingCriterion(pointsRequiredToPass=" + this.getPointsRequiredToPass() + + ", fx=" + this.isFx() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- + @Override + protected boolean canEqual(final Object other) { + return other instanceof AbstractGradingCriterion; + } + + public abstract boolean isProjectCriterion(); + + public abstract boolean isIndividualCriterion(); + + public abstract int getMaxPoints(); + + // ---------------------------------------------------------------------------------- + // Nested type + // ---------------------------------------------------------------------------------- public enum Flag { /** * Criterion marked with this flag will add extra functionality related @@ -25,91 +127,4 @@ public abstract class AbstractGradingCriterion extends AbstractCriterion { */ OPPOSITION } - - @Basic(optional = false) - protected int pointsRequiredToPass; - - @Basic - private boolean fx = true; - - @Basic - @Column(name = "flag") - @Enumerated(EnumType.STRING) - private Flag flag; - - protected AbstractGradingCriterion() { - - } - - protected AbstractGradingCriterion(String title, String titleEn, int sortOrder, int pointsRequiredToPass) { - super(title, titleEn, sortOrder); - this.pointsRequiredToPass = pointsRequiredToPass; - } - - protected AbstractGradingCriterion( - String title, - String titleEn, - Integer sortOrder, - int pointsRequiredToPass, - Flag flag) - { - this(title, titleEn, sortOrder, pointsRequiredToPass); - this.flag = flag; - } - - public abstract boolean isProjectCriterion(); - - public abstract boolean isIndividualCriterion(); - - public abstract int getMaxPoints(); - - public int getPointsRequiredToPass() { - return this.pointsRequiredToPass; - } - - public boolean isFx() { - return this.fx; - } - - public Flag getFlag() { - return flag; - } - - public void setFlag(Flag flag) { - this.flag = flag; - } - - @Override - public boolean equals(final Object o) { - if (o == this) return true; - if (!(o instanceof AbstractGradingCriterion)) return false; - final AbstractGradingCriterion other = (AbstractGradingCriterion) o; - return other.canEqual(this) - && super.equals(o) - && this.getPointsRequiredToPass() == other.getPointsRequiredToPass() - && this.isFx() == other.isFx(); - } - - @Override - protected boolean canEqual(final Object other) { - return other instanceof AbstractGradingCriterion; - } - - @Override - public int hashCode() { - final int PRIME = 59; - int result = super.hashCode(); - result = result * PRIME + this.getPointsRequiredToPass(); - result = result * PRIME + (this.isFx() ? 79 : 97); - return result; - } - - @Override - public String toString() { - return "AbstractGradingCriterion(pointsRequiredToPass=" + this.getPointsRequiredToPass() + ", fx=" + this.isFx() + ")"; - } - - public void setFx(boolean fx) { - this.fx = fx; - } } diff --git a/core/src/main/java/se/su/dsv/scipro/report/AbstractGradingCriterionPoint.java b/core/src/main/java/se/su/dsv/scipro/report/AbstractGradingCriterionPoint.java index ae653266ac..29e423d0f2 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/AbstractGradingCriterionPoint.java +++ b/core/src/main/java/se/su/dsv/scipro/report/AbstractGradingCriterionPoint.java @@ -1,70 +1,86 @@ package se.su.dsv.scipro.report; -import se.su.dsv.scipro.system.DomainObject; - -import jakarta.persistence.*; -import se.su.dsv.scipro.system.Language; - import java.util.Objects; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.MappedSuperclass; +import se.su.dsv.scipro.system.DomainObject; + +import se.su.dsv.scipro.system.Language; + @MappedSuperclass -public abstract class AbstractGradingCriterionPoint extends DomainObject implements Comparable<AbstractGradingCriterionPoint> { +public abstract class AbstractGradingCriterionPoint extends DomainObject + implements Comparable<AbstractGradingCriterionPoint> { public static final int DESCRIPTION_LENGTH = 600; + + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Basic(optional = false) + @Column(name = "point") private Integer point; @Basic - @Column(length = DESCRIPTION_LENGTH) + @Column(name = "description_sv", length = DESCRIPTION_LENGTH) private String description; @Basic - @Column(length = DESCRIPTION_LENGTH) + @Column(name = "description_en", length = DESCRIPTION_LENGTH) private String descriptionEn; + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- public AbstractGradingCriterionPoint() { } + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- @Override public Long getId() { return id; } - public Integer getPoint() { - return this.point; - } - - public String getDescription() { - return this.description; - } - - public String getDescriptionEn() { - return descriptionEn; - } - - public String getDescription(Language language) { - return language == Language.ENGLISH ? getDescriptionEn() : getDescription(); - } - public void setId(Long id) { this.id = id; } + public Integer getPoint() { + return this.point; + } + public void setPoint(Integer point) { this.point = point; } + public String getDescription() { + return this.description; + } + public void setDescription(String description) { this.description = description; } + public String getDescriptionEn() { + return descriptionEn; + } + public void setDescriptionEn(String descriptionEn) { this.descriptionEn = descriptionEn; } + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects and Comparable + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -78,10 +94,6 @@ public abstract class AbstractGradingCriterionPoint extends DomainObject impleme && Objects.equals(this.getDescriptionEn(), other.getDescriptionEn()); } - protected boolean canEqual(final Object other) { - return other instanceof AbstractGradingCriterionPoint; - } - @Override public int hashCode() { return Objects.hash(super.hashCode(), this.getId(), this.getPoint(), this.getDescription(), this.getDescriptionEn()); @@ -91,4 +103,15 @@ public abstract class AbstractGradingCriterionPoint extends DomainObject impleme public String toString() { return "AbstractGradingCriterionPoint(id=" + this.getId() + ", point=" + this.getPoint() + ", description=" + this.getDescription() + ", descriptionEn=" + this.getDescriptionEn() + ")"; } + + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof AbstractGradingCriterionPoint; + } + + public String getDescription(Language language) { + return language == Language.ENGLISH ? getDescriptionEn() : getDescription(); + } } diff --git a/core/src/main/java/se/su/dsv/scipro/report/AttachmentReport.java b/core/src/main/java/se/su/dsv/scipro/report/AttachmentReport.java index 3ec5ea0ac4..53c135a971 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/AttachmentReport.java +++ b/core/src/main/java/se/su/dsv/scipro/report/AttachmentReport.java @@ -6,16 +6,23 @@ import jakarta.persistence.CascadeType; import jakarta.persistence.JoinColumn; import jakarta.persistence.MappedSuperclass; import jakarta.persistence.OneToOne; -import java.util.*; +import java.util.Objects; @MappedSuperclass public abstract class AttachmentReport extends Report { + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in table of children class (OppositionReport) + // referencing other tables. + // ---------------------------------------------------------------------------------- @OneToOne(optional = true, cascade = CascadeType.ALL) - @JoinColumn(name = "attachment_reference_id") + @JoinColumn(name = "attachment_file_reference_id", referencedColumnName = "id") private FileReference attachment; + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public FileReference getAttachment() { return this.attachment; } @@ -24,6 +31,9 @@ public abstract class AttachmentReport extends Report { this.attachment = attachment; } + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -34,14 +44,16 @@ public abstract class AttachmentReport extends Report { && Objects.equals(this.attachment, other.attachment); } - @Override - protected boolean canEqual(final Object other) { - return other instanceof AttachmentReport; - } - @Override public int hashCode() { return Objects.hash(super.hashCode(), this.attachment); } + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- + @Override + protected boolean canEqual(final Object other) { + return other instanceof AttachmentReport; + } } diff --git a/core/src/main/java/se/su/dsv/scipro/report/Criterion.java b/core/src/main/java/se/su/dsv/scipro/report/Criterion.java index de823bdb5c..63978c9170 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/Criterion.java +++ b/core/src/main/java/se/su/dsv/scipro/report/Criterion.java @@ -1,6 +1,11 @@ package se.su.dsv.scipro.report; -import jakarta.persistence.*; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; import se.su.dsv.scipro.system.Language; import java.util.Objects; @@ -8,26 +13,34 @@ import java.util.Objects; @Entity @Table(name = "criterion") public class Criterion extends AbstractCriterion { - public static final int DESCRIPTION_LENGTH = 2000; - @ManyToOne(optional = false) - private Report report; - + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Basic - @Column - private String feedback; - - @Basic - @Column(length = DESCRIPTION_LENGTH) + @Column(name = "description_sv", length = DESCRIPTION_LENGTH) private String description; @Basic - @Column(length = DESCRIPTION_LENGTH) + @Column(name = "description_en", length = DESCRIPTION_LENGTH) private String descriptionEn; - protected Criterion() { + @Basic + @Column(name = "feedback") + private String feedback; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (criterion) referencing other tables. + // ---------------------------------------------------------------------------------- + @ManyToOne(optional = false) + @JoinColumn(name ="report_id", referencedColumnName = "id") + private Report report; + + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- + protected Criterion() { } Criterion(Report report, String title, String titleEn, String description, String descriptionEn, int sortOrder) { @@ -41,22 +54,9 @@ public class Criterion extends AbstractCriterion { this(report, gradingCriterionTemplate.getTitle(), gradingCriterionTemplate.getTitleEn(), gradingCriterionTemplate.getDescription(), gradingCriterionTemplate.getDescriptionEn(), gradingCriterionTemplate.getSortOrder()); } - public void setFeedback(final String feedback) { - this.feedback = feedback; - } - - public boolean isFilledOut() { - return feedback != null && !feedback.isEmpty(); - } - - public Report getReport() { - return this.report; - } - - public String getFeedback() { - return this.feedback; - } - + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public String getDescription() { return this.description; } @@ -65,10 +65,21 @@ public class Criterion extends AbstractCriterion { return this.descriptionEn; } - public String getDescription(Language language) { - return language == Language.ENGLISH ? getDescriptionEn() : getDescription(); + public String getFeedback() { + return this.feedback; } + public void setFeedback(final String feedback) { + this.feedback = feedback; + } + + public Report getReport() { + return this.report; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -82,11 +93,6 @@ public class Criterion extends AbstractCriterion { && Objects.equals(this.getDescriptionEn(), other.getDescriptionEn()); } - @Override - protected boolean canEqual(final Object other) { - return other instanceof Criterion; - } - @Override public int hashCode() { return Objects.hash(this.getReport(), this.getFeedback(), this.getDescription(), this.getDescriptionEn()); @@ -94,6 +100,24 @@ public class Criterion extends AbstractCriterion { @Override public String toString() { - return "Criterion(report=" + this.getReport() + ", feedback=" + this.getFeedback() + ", description=" + this.getDescription() + ", descriptionEn=" + this.getDescriptionEn() + ")"; + return "Criterion(report=" + this.getReport() + ", feedback=" + this.getFeedback() + + ", description=" + this.getDescription() + ", descriptionEn=" + + this.getDescriptionEn() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- + @Override + protected boolean canEqual(final Object other) { + return other instanceof Criterion; + } + + public String getDescription(Language language) { + return language == Language.ENGLISH ? getDescriptionEn() : getDescription(); + } + + public boolean isFilledOut() { + return feedback != null && !feedback.isEmpty(); } } diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradeLimit.java b/core/src/main/java/se/su/dsv/scipro/report/GradeLimit.java index 49d6b60097..385d4941f3 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/GradeLimit.java +++ b/core/src/main/java/se/su/dsv/scipro/report/GradeLimit.java @@ -1,5 +1,6 @@ package se.su.dsv.scipro.report; +import jakarta.persistence.Basic; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -8,18 +9,26 @@ import jakarta.persistence.Id; import jakarta.persistence.Table; @Entity -@Table(name = "grading_report_template_grade_limits") +@Table(name = "grading_report_template_grade_limit") public class GradeLimit { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Basic @Column(name = "grade") private String grade; + @Basic @Column(name = "lower_limit") private int lowerLimit; + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public Long getId() { return id; } diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradingCriterion.java b/core/src/main/java/se/su/dsv/scipro/report/GradingCriterion.java index aad898db4c..10ea7059b0 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/GradingCriterion.java +++ b/core/src/main/java/se/su/dsv/scipro/report/GradingCriterion.java @@ -1,30 +1,57 @@ package se.su.dsv.scipro.report; -import jakarta.persistence.*; +import jakarta.persistence.Basic; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.DiscriminatorColumn; +import jakarta.persistence.Entity; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; + import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; @Entity -@DiscriminatorColumn(name = "type") +@Table(name = "grading_criterion") @Inheritance(strategy = InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn(name = "type") public abstract class GradingCriterion extends AbstractGradingCriterion { public static final int FEEDBACK_LENGTH = 2000; - @ManyToOne(optional = false) - private GradingReport gradingReport; - - @OneToMany(mappedBy = "gradingCriterion", orphanRemoval = true, cascade = CascadeType.PERSIST) - private List<GradingCriterionPoint> gradingCriterionPoints = new ArrayList<>(); - + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Basic + @Column(name = "points") private Integer points; @Basic - @Column(length = FEEDBACK_LENGTH) + @Column(name = "feedback", length = FEEDBACK_LENGTH) private String feedback; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (grading_criterion) referencing other + // tables. + // ---------------------------------------------------------------------------------- + @ManyToOne(optional = false) + @JoinColumn(name = "grading_report_id", referencedColumnName = "id") + private GradingReport gradingReport; + // ---------------------------------------------------------------------------------- + // JPA-mappings of other tables referencing to this table "grading_criterion" + // ---------------------------------------------------------------------------------- + @OneToMany(mappedBy = "gradingCriterion", orphanRemoval = true, cascade = CascadeType.PERSIST) + private List<GradingCriterionPoint> gradingCriterionPoints = new ArrayList<>(); + + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- protected GradingCriterion() { // JPA } @@ -41,6 +68,71 @@ public abstract class GradingCriterion extends AbstractGradingCriterion { } } + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- + public Integer getPoints() { + return this.points; + } + + public void setPoints(Integer points) { + this.points = points; + } + + public String getFeedback() { + return this.feedback; + } + + public void setFeedback(String feedback) { + this.feedback = feedback; + } + + public List<GradingCriterionPoint> getGradingCriterionPoints() { + return this.gradingCriterionPoints; + } + + public GradingReport getGradingReport() { + return this.gradingReport; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- + @Override + public boolean equals(final Object o) { + if (o == this) return true; + if (!(o instanceof GradingCriterion)) return false; + final GradingCriterion other = (GradingCriterion) o; + return other.canEqual(this) + && super.equals(o) + && Objects.equals(this.getGradingReport(), other.getGradingReport()) + && Objects.equals(this.getPoints(), other.getPoints()) + && Objects.equals(this.getFeedback(), other.getFeedback()); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), this.getGradingReport(), this.getPoints(), this.getFeedback()); + } + + @Override + public String toString() { + return "GradingCriterion(gradingReport=" + this.getGradingReport() + ", points=" + this.getPoints() + + ", feedback=" + this.getFeedback() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- + @Override + protected boolean canEqual(final Object other) { + return other instanceof GradingCriterion; + } + + public boolean isPassFail() { + return getMaxPoints() == 1 && getPointsRequiredToPass() == 1; + } + public boolean meetsMinimumPointRequirement() { return Objects.requireNonNullElse(getPoints(), 0) >= getPointsRequiredToPass(); } @@ -57,59 +149,4 @@ public abstract class GradingCriterion extends AbstractGradingCriterion { public int getMaxPoints() { return Collections.max(gradingCriterionPoints).getPoint(); } - - public GradingReport getGradingReport() { - return this.gradingReport; - } - - public Integer getPoints() { - return this.points; - } - - public String getFeedback() { - return this.feedback; - } - - public List<GradingCriterionPoint> getGradingCriterionPoints() { - return this.gradingCriterionPoints; - } - - public void setPoints(Integer points) { - this.points = points; - } - - public void setFeedback(String feedback) { - this.feedback = feedback; - } - - @Override - public boolean equals(final Object o) { - if (o == this) return true; - if (!(o instanceof GradingCriterion)) return false; - final GradingCriterion other = (GradingCriterion) o; - return other.canEqual(this) - && super.equals(o) - && Objects.equals(this.getGradingReport(), other.getGradingReport()) - && Objects.equals(this.getPoints(), other.getPoints()) - && Objects.equals(this.getFeedback(), other.getFeedback()); - } - - @Override - protected boolean canEqual(final Object other) { - return other instanceof GradingCriterion; - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), this.getGradingReport(), this.getPoints(), this.getFeedback()); - } - - @Override - public String toString() { - return "GradingCriterion(gradingReport=" + this.getGradingReport() + ", points=" + this.getPoints() + ", feedback=" + this.getFeedback() + ")"; - } - - public boolean isPassFail() { - return getMaxPoints() == 1 && getPointsRequiredToPass() == 1; - } } diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradingCriterionPoint.java b/core/src/main/java/se/su/dsv/scipro/report/GradingCriterionPoint.java index 5c8734af9b..6c516f95b4 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/GradingCriterionPoint.java +++ b/core/src/main/java/se/su/dsv/scipro/report/GradingCriterionPoint.java @@ -1,37 +1,39 @@ package se.su.dsv.scipro.report; import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; import java.util.Objects; @Entity -@Table(name = "GradingCriterionPoint") +@Table(name = "grading_criterion_point") public class GradingCriterionPoint extends AbstractGradingCriterionPoint { - + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (grading_criterion_point) referencing other + // tables. + // ---------------------------------------------------------------------------------- @ManyToOne(optional = false) + @JoinColumn(name = "grading_criterion_id", referencedColumnName = "id") private GradingCriterion gradingCriterion; + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- public GradingCriterionPoint() { } - public GradingCriterionPoint( - final Integer point, - final String description, - final String descriptionEn, - final GradingCriterion gradingCriterion) - { + public GradingCriterionPoint(final Integer point, final String description, + final String descriptionEn, final GradingCriterion gradingCriterion) { setPoint(point); setDescription(description); setDescriptionEn(descriptionEn); this.gradingCriterion = gradingCriterion; } - @Override - public int compareTo(AbstractGradingCriterionPoint abstractGradingCriterionPoint) { - return this.getPoint().compareTo(abstractGradingCriterionPoint.getPoint()); - } - + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public GradingCriterion getGradingCriterion() { return this.gradingCriterion; } @@ -40,9 +42,12 @@ public class GradingCriterionPoint extends AbstractGradingCriterionPoint { this.gradingCriterion = gradingCriterion; } + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects and Comparable + // ---------------------------------------------------------------------------------- @Override - public String toString() { - return "GradingCriterionPoint(gradingCriterion=" + this.getGradingCriterion() + ")"; + public int compareTo(AbstractGradingCriterionPoint abstractGradingCriterionPoint) { + return this.getPoint().compareTo(abstractGradingCriterionPoint.getPoint()); } @Override @@ -55,13 +60,22 @@ public class GradingCriterionPoint extends AbstractGradingCriterionPoint { && Objects.equals(this.getGradingCriterion(), other.getGradingCriterion()); } + @Override + public int hashCode() { + return Objects.hashCode(this.getGradingCriterion()); + } + + @Override + public String toString() { + return "GradingCriterionPoint(gradingCriterion=" + this.getGradingCriterion() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- @Override protected boolean canEqual(final Object other) { return other instanceof GradingCriterionPoint; } - @Override - public int hashCode() { - return Objects.hashCode(this.getGradingCriterion()); - } } diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradingCriterionPointTemplate.java b/core/src/main/java/se/su/dsv/scipro/report/GradingCriterionPointTemplate.java index 88708ddf1d..a41785948a 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/GradingCriterionPointTemplate.java +++ b/core/src/main/java/se/su/dsv/scipro/report/GradingCriterionPointTemplate.java @@ -1,8 +1,10 @@ package se.su.dsv.scipro.report; import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; + import java.util.Objects; @Entity @@ -10,6 +12,7 @@ import java.util.Objects; public class GradingCriterionPointTemplate extends AbstractGradingCriterionPoint { @ManyToOne(optional = false) + @JoinColumn(name = "grading_criterion_template_id", nullable = false) private GradingCriterionTemplate gradingCriterionTemplate; @Override diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradingCriterionTemplate.java b/core/src/main/java/se/su/dsv/scipro/report/GradingCriterionTemplate.java index 6feaee5bd8..92ab7539dc 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/GradingCriterionTemplate.java +++ b/core/src/main/java/se/su/dsv/scipro/report/GradingCriterionTemplate.java @@ -1,18 +1,29 @@ package se.su.dsv.scipro.report; -import jakarta.persistence.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; +import jakarta.persistence.CascadeType; +import jakarta.persistence.DiscriminatorColumn; +import jakarta.persistence.Entity; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; + @Entity -@DiscriminatorColumn(name = "type", length = GradingCriterionTemplate.LENGTH) -@Inheritance(strategy = InheritanceType.SINGLE_TABLE) @Table(name = "grading_criterion_template") +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn(name = "type", length = GradingCriterionTemplate.LENGTH) public abstract class GradingCriterionTemplate extends AbstractGradingCriterion { public static final int LENGTH = 64; + @ManyToOne(optional = false) + @JoinColumn(name = "grading_report_template_id") private GradingReportTemplate gradingReportTemplate; @OneToMany(mappedBy = "gradingCriterionTemplate", orphanRemoval = true, cascade = CascadeType.ALL) diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradingReport.java b/core/src/main/java/se/su/dsv/scipro/report/GradingReport.java index 0c036ede48..6957cae4d5 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/GradingReport.java +++ b/core/src/main/java/se/su/dsv/scipro/report/GradingReport.java @@ -1,11 +1,19 @@ package se.su.dsv.scipro.report; +import jakarta.persistence.Basic; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.Language; import se.su.dsv.scipro.system.ProjectType; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.time.Instant; import java.util.ArrayList; import java.util.Collections; @@ -13,6 +21,7 @@ import java.util.List; import java.util.stream.Collectors; @Entity +@Table(name = "grading_report") public abstract class GradingReport extends Report { public record Grade(String name) { @@ -27,40 +36,51 @@ public abstract class GradingReport extends Report { public enum State { INITIAL, REVIEWING, FINALIZED } + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- + @Basic + @Column(name = "state") @Enumerated(EnumType.STRING) private State state = State.INITIAL; - @ManyToOne(optional = false) - private Project project; - - @OneToMany(mappedBy = "gradingReport", cascade = {CascadeType.ALL}) - private List<GradingCriterion> gradingCriteria = new ArrayList<>(); - @Basic @Column(name = "date_submitted_to_examiner") private Instant dateSubmittedToExaminer; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (grading_report) referencing other + // tables. + // ---------------------------------------------------------------------------------- + @ManyToOne(optional = false) + private Project project; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of other tables referencing to this table "grading_report" + // ---------------------------------------------------------------------------------- + @OneToMany(mappedBy = "gradingReport", cascade = {CascadeType.ALL}) + private List<GradingCriterion> gradingCriteria = new ArrayList<>(); + + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- protected GradingReport() { // JPA } - @Override - public void submit() { - super.submit(); - setState(State.FINALIZED); - setDateSubmittedToExaminer(Instant.now()); - } - - public Project getProject() { - return project; - } - GradingReport(Project project) { this.project = project; } - void addCriterion(GradingCriterion criterion) { - gradingCriteria.add(criterion); + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- + public State getState() { + return state; + } + + public void setState(final State state) { + this.state = state; } public Instant getDateSubmittedToExaminer(){ @@ -71,12 +91,8 @@ public abstract class GradingReport extends Report { this.dateSubmittedToExaminer = dateSubmittedToExaminer; } - public State getState() { - return state; - } - - public void setState(final State state) { - this.state = state; + public Project getProject() { + return project; } public List<GradingCriterion> getGradingCriteria() { @@ -84,6 +100,21 @@ public abstract class GradingReport extends Report { return Collections.unmodifiableList(gradingCriteria); } + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- + @Override + public String toString() { + return "GradingReport(state=" + this.getState() + ", project=" + this.getProject() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- + void addCriterion(GradingCriterion criterion) { + gradingCriteria.add(criterion); + } + public String getProjectTitle() { return project.getTitle(); } @@ -112,7 +143,9 @@ public abstract class GradingReport extends Report { } @Override - public String toString() { - return "GradingReport(state=" + this.getState() + ", project=" + this.getProject() + ")"; + public void submit() { + super.submit(); + setState(State.FINALIZED); + setDateSubmittedToExaminer(Instant.now()); } } diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplate.java b/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplate.java index cc106b6c95..f8b5c9c8c3 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplate.java +++ b/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplate.java @@ -1,13 +1,24 @@ package se.su.dsv.scipro.report; +import jakarta.persistence.Basic; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import jakarta.persistence.Temporal; +import jakarta.persistence.TemporalType; import se.su.dsv.scipro.finalseminar.FinalSeminarOpposition; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.ProjectType; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; - import java.time.LocalDate; import java.util.ArrayList; import java.util.Collection; @@ -19,18 +30,16 @@ import java.util.Objects; @Table(name = "grading_report_template") public class GradingReportTemplate extends DomainObject { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToOne(optional = false) - private ProjectType projectType; - - @OneToMany(mappedBy = "gradingReportTemplate", cascade = {CascadeType.ALL}, orphanRemoval = true) - private Collection<GradingCriterionTemplate> criteria = new HashSet<>(); - - @Temporal(TemporalType.DATE) + @Basic @Column(name = "valid_from") + @Temporal(TemporalType.DATE) private LocalDate validFrom; @Basic @@ -41,10 +50,27 @@ public class GradingReportTemplate extends DomainObject { @Column(name = "failing_grade") private String failingGrade; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (grading_report_template) referencing + // other tables. + // ---------------------------------------------------------------------------------- + @OneToOne(optional = false) + @JoinColumn(name = "project_type_id", referencedColumnName = "id") + private ProjectType projectType; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of other tables referencing to this table "grading_report_template" + // ---------------------------------------------------------------------------------- + @OneToMany(mappedBy = "gradingReportTemplate", cascade = {CascadeType.ALL}, orphanRemoval = true) + private Collection<GradingCriterionTemplate> criteria = new HashSet<>(); + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) - @JoinColumn(name = "grading_report_template_id") + @JoinColumn(name = "grading_report_template_id", referencedColumnName = "id") private Collection<GradeLimit> gradeLimits = new ArrayList<>(); + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- protected GradingReportTemplate() { } @@ -57,43 +83,9 @@ public class GradingReportTemplate extends DomainObject { this.validFrom = validFrom; } - public SupervisorGradingReport createSupervisorReport(Project project, User student) { - if (!this.projectType.equals(project.getProjectType())) { - throw new IllegalArgumentException("Project has a different project class than this template"); - } - return new SupervisorGradingReportFactory().using(criteria).create(project, student); - } - - public OppositionReport createOppositionReport(FinalSeminarOpposition finalSeminarOpposition) { - return new OppositionReport(this, finalSeminarOpposition); - } - - public GradingCriterionTemplate addProjectCriterion(String title, String titleEn, int pointsRequiredToPass, List<GradingCriterionPointTemplate> gradingCriterionPointTemplates) { - return addProjectCriterion(title, titleEn, pointsRequiredToPass, gradingCriterionPointTemplates, null); - } - - public GradingCriterionTemplate addProjectCriterion(String title, String titleEn, int pointsRequiredToPass, List<GradingCriterionPointTemplate> gradingCriterionPointTemplates, AbstractGradingCriterion.Flag flag) { - GradingCriterionTemplate gradingCriterionTemplate = new ProjectGradingCriterionTemplate(this, criteria.size(), title, titleEn, pointsRequiredToPass, gradingCriterionPointTemplates); - gradingCriterionTemplate.setFlag(flag); - criteria.add(gradingCriterionTemplate); - return gradingCriterionTemplate; - } - - public GradingCriterionTemplate addIndividualCriterion(String title, String titleEn, int pointsRequiredToPass, List<GradingCriterionPointTemplate> gradingCriterionPointTemplates) { - return addIndividualCriterion(title, titleEn, pointsRequiredToPass, gradingCriterionPointTemplates, null); - } - - public GradingCriterionTemplate addIndividualCriterion(String title, String titleEn, int pointsRequiredToPass, List<GradingCriterionPointTemplate> gradingCriterionPointTemplates, AbstractGradingCriterion.Flag flag) { - GradingCriterionTemplate gradingCriterionTemplate = new IndividualGradingCriterionTemplate(this, criteria.size(), title, titleEn, pointsRequiredToPass, gradingCriterionPointTemplates); - gradingCriterionTemplate.setFlag(flag); - criteria.add(gradingCriterionTemplate); - return gradingCriterionTemplate; - } - - public Collection<GradingCriterionTemplate> getCriteria() { - return criteria; - } - + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- @Override public Long getId() { return this.id; @@ -107,14 +99,6 @@ public class GradingReportTemplate extends DomainObject { this.validFrom = validFrom; } - public ProjectType getProjectType() { - return projectType; - } - - public void setProjectType(ProjectType projectType) { - this.projectType = projectType; - } - public String getNote() { return note; } @@ -131,6 +115,18 @@ public class GradingReportTemplate extends DomainObject { this.failingGrade = failingGrade; } + public ProjectType getProjectType() { + return projectType; + } + + public void setProjectType(ProjectType projectType) { + this.projectType = projectType; + } + + public Collection<GradingCriterionTemplate> getCriteria() { + return criteria; + } + public Collection<GradeLimit> getGradeLimits() { return gradeLimits; } @@ -139,6 +135,9 @@ public class GradingReportTemplate extends DomainObject { this.gradeLimits = gradeLimits; } + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -148,10 +147,6 @@ public class GradingReportTemplate extends DomainObject { && Objects.equals(this.id, other.id); } - protected boolean canEqual(final Object other) { - return other instanceof GradingReportTemplate; - } - @Override public int hashCode() { return Objects.hashCode(this.id); @@ -159,6 +154,56 @@ public class GradingReportTemplate extends DomainObject { @Override public String toString() { - return "GradingReportTemplate(id=" + this.id + ", projectType=" + this.projectType + ", validFrom=" + this.validFrom + ")"; + return "GradingReportTemplate(id=" + this.id + ", projectType=" + this.projectType + ", validFrom=" + + this.validFrom + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- + public SupervisorGradingReport createSupervisorReport(Project project, User student) { + if (!this.projectType.equals(project.getProjectType())) { + throw new IllegalArgumentException("Project has a different project class than this template"); + } + return new SupervisorGradingReportFactory().using(criteria).create(project, student); + } + + public OppositionReport createOppositionReport(FinalSeminarOpposition finalSeminarOpposition) { + return new OppositionReport(this, finalSeminarOpposition); + } + + public GradingCriterionTemplate addProjectCriterion(String title, String titleEn, int pointsRequiredToPass, + List<GradingCriterionPointTemplate> gradingCriterionPointTemplates) { + return addProjectCriterion(title, titleEn, pointsRequiredToPass, gradingCriterionPointTemplates, null); + } + + public GradingCriterionTemplate addProjectCriterion(String title, String titleEn, int pointsRequiredToPass, + List<GradingCriterionPointTemplate> gradingCriterionPointTemplates, + AbstractGradingCriterion.Flag flag) { + GradingCriterionTemplate gradingCriterionTemplate = new ProjectGradingCriterionTemplate(this, + criteria.size(), title, titleEn, pointsRequiredToPass, gradingCriterionPointTemplates); + gradingCriterionTemplate.setFlag(flag); + criteria.add(gradingCriterionTemplate); + return gradingCriterionTemplate; + } + + public GradingCriterionTemplate addIndividualCriterion(String title, String titleEn, int pointsRequiredToPass, + List<GradingCriterionPointTemplate> gradingCriterionPointTemplates) { + return addIndividualCriterion(title, titleEn, pointsRequiredToPass, gradingCriterionPointTemplates, null); + } + + public GradingCriterionTemplate addIndividualCriterion(String title, String titleEn, int pointsRequiredToPass, + List<GradingCriterionPointTemplate> gradingCriterionPointTemplates, + AbstractGradingCriterion.Flag flag) { + GradingCriterionTemplate gradingCriterionTemplate = new IndividualGradingCriterionTemplate(this, + criteria.size(), title, titleEn, pointsRequiredToPass, gradingCriterionPointTemplates); + gradingCriterionTemplate.setFlag(flag); + criteria.add(gradingCriterionTemplate); + return gradingCriterionTemplate; + } + + + protected boolean canEqual(final Object other) { + return other instanceof GradingReportTemplate; } } diff --git a/core/src/main/java/se/su/dsv/scipro/report/OppositionReport.java b/core/src/main/java/se/su/dsv/scipro/report/OppositionReport.java index 5775a6db0b..426e393399 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/OppositionReport.java +++ b/core/src/main/java/se/su/dsv/scipro/report/OppositionReport.java @@ -1,10 +1,17 @@ package se.su.dsv.scipro.report; +import jakarta.persistence.Basic; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; import se.su.dsv.scipro.finalseminar.FinalSeminarOpposition; import se.su.dsv.scipro.system.Language; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -15,56 +22,57 @@ import java.util.stream.Collectors; @Table(name = "opposition_report") public class OppositionReport extends AttachmentReport { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- + @Basic + @Column(name = "thesis_summary") + private String thesisSummary; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (opposition_report) referencing other + // tables. + // ---------------------------------------------------------------------------------- @OneToOne(optional = false) + @JoinColumn(name = "final_seminar_opposition_id", referencedColumnName = "id") private FinalSeminarOpposition finalSeminarOpposition; + // ---------------------------------------------------------------------------------- + // JPA-mappings of other tables referencing to this table "opposition_report" + // ---------------------------------------------------------------------------------- @OneToMany(mappedBy = "report", cascade = {CascadeType.ALL}) private List<Criterion> oppositionCriteria = new ArrayList<>(); - @Basic - @Column - private String thesisSummary; - - + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- protected OppositionReport() { - } - public OppositionReport(GradingReportTemplate gradingReportTemplate, FinalSeminarOpposition finalSeminarOpposition) { + public OppositionReport(GradingReportTemplate gradingReportTemplate, + FinalSeminarOpposition finalSeminarOpposition) { this.finalSeminarOpposition = finalSeminarOpposition; createCriteriaFromTemplate(gradingReportTemplate); } - private void createCriteriaFromTemplate(GradingReportTemplate gradingReportTemplate) { - for (GradingCriterionTemplate template : gradingReportTemplate.getCriteria()) { - if (template.isProjectCriterion()) { - oppositionCriteria.add(new Criterion(this, template)); - } - } + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- + public String getThesisSummary() { + return this.thesisSummary; } - public List<Criterion> getCriteria() { - oppositionCriteria.sort(new AbstractCriterion.BySortOrderComparator()); - return Collections.unmodifiableList(oppositionCriteria); + public void setThesisSummary(String thesisSummary) { + this.thesisSummary = thesisSummary; } - @Override - public boolean isFinished() { - if (thesisSummaryIsEmpty()) { - return false; - } - for (Criterion criterion : oppositionCriteria) { - if (!criterion.isFilledOut()) { - return false; - } - } - return true; - } - - private boolean thesisSummaryIsEmpty() { - return thesisSummary == null || thesisSummary.isEmpty(); + public FinalSeminarOpposition getFinalSeminarOpposition() { + return this.finalSeminarOpposition; } + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- public User getUser() { return finalSeminarOpposition.getUser(); } @@ -110,15 +118,33 @@ public class OppositionReport extends AttachmentReport { return finalSeminarOpposition.getUser().getLastName(); } - public FinalSeminarOpposition getFinalSeminarOpposition() { - return this.finalSeminarOpposition; + private void createCriteriaFromTemplate(GradingReportTemplate gradingReportTemplate) { + for (GradingCriterionTemplate template : gradingReportTemplate.getCriteria()) { + if (template.isProjectCriterion()) { + oppositionCriteria.add(new Criterion(this, template)); + } + } } - public String getThesisSummary() { - return this.thesisSummary; + public List<Criterion> getCriteria() { + oppositionCriteria.sort(new AbstractCriterion.BySortOrderComparator()); + return Collections.unmodifiableList(oppositionCriteria); } - public void setThesisSummary(String thesisSummary) { - this.thesisSummary = thesisSummary; + @Override + public boolean isFinished() { + if (thesisSummaryIsEmpty()) { + return false; + } + for (Criterion criterion : oppositionCriteria) { + if (!criterion.isFilledOut()) { + return false; + } + } + return true; + } + + private boolean thesisSummaryIsEmpty() { + return thesisSummary == null || thesisSummary.isEmpty(); } } diff --git a/core/src/main/java/se/su/dsv/scipro/report/Report.java b/core/src/main/java/se/su/dsv/scipro/report/Report.java index dd1437fc18..da88711b3b 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/Report.java +++ b/core/src/main/java/se/su/dsv/scipro/report/Report.java @@ -1,48 +1,36 @@ package se.su.dsv.scipro.report; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.Table; import se.su.dsv.scipro.system.DomainObject; -import jakarta.persistence.*; import java.util.Objects; @Entity @Table(name = "report") @Inheritance(strategy = InheritanceType.JOINED) public abstract class Report extends DomainObject { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Basic(optional = false) + @Column(name = "submitted") private boolean submitted = false; - public abstract boolean isFinished(); - - public void submit() { - if (!isFinished()) { - throw new IllegalStateException("Report is not finished: you need to score and give feedback to every criteria"); - } - submitted = true; - } - - @Override - public boolean equals(final Object o) { - if (o == this) return true; - if (!(o instanceof Report)) return false; - final Report other = (Report) o; - return other.canEqual(this) - && Objects.equals(this.id, other.id); - } - - protected boolean canEqual(final Object other) { - return other instanceof Report; - } - - @Override - public int hashCode() { - return Objects.hashCode(this.id); - } - + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- @Override public Long getId() { return this.id; @@ -55,4 +43,37 @@ public abstract class Report extends DomainObject { public void setSubmitted(boolean submitted) { this.submitted = submitted; } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- + @Override + public boolean equals(final Object o) { + if (o == this) return true; + if (!(o instanceof Report)) return false; + final Report other = (Report) o; + return other.canEqual(this) + && Objects.equals(this.id, other.id); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.id); + } + + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof Report; + } + + public abstract boolean isFinished(); + + public void submit() { + if (!isFinished()) { + throw new IllegalStateException("Report is not finished: you need to score and give feedback to every criteria"); + } + submitted = true; + } } diff --git a/core/src/main/java/se/su/dsv/scipro/report/SupervisorGradingReport.java b/core/src/main/java/se/su/dsv/scipro/report/SupervisorGradingReport.java index b3e682dfba..59b4bca6b8 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/SupervisorGradingReport.java +++ b/core/src/main/java/se/su/dsv/scipro/report/SupervisorGradingReport.java @@ -1,26 +1,24 @@ package se.su.dsv.scipro.report; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import se.su.dsv.scipro.project.Project; -import se.su.dsv.scipro.system.User; - import jakarta.persistence.Basic; import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import se.su.dsv.scipro.project.Project; +import se.su.dsv.scipro.system.User; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @Entity +@Table(name = "supervisor_grading_report") public class SupervisorGradingReport extends GradingReport { - - private static final Logger LOG = LoggerFactory.getLogger(SupervisorGradingReport.class); - - @ManyToOne(optional = false) - private User user; - + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Basic @Column(name = "rejection_comment") private String rejectionComment; @@ -33,6 +31,17 @@ public class SupervisorGradingReport extends GradingReport { @Column(name = "motivation") private String motivation; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (grading_criterion) referencing other + // tables. + // ---------------------------------------------------------------------------------- + @ManyToOne(optional = false) + @JoinColumn(name = "user_id", referencedColumnName = "id") + private User user; + + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- protected SupervisorGradingReport() { // JPA } @@ -42,6 +51,40 @@ public class SupervisorGradingReport extends GradingReport { this.user = user; } + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- + public User getUser() { + return this.user; + } + + public String getRejectionComment() { + return rejectionComment; + } + + public void setRejectionComment(String rejectionComment) { + this.rejectionComment = rejectionComment; + } + + public String getRejectionCommentFeedback() { + return rejectionCommentFeedback; + } + + public void setRejectionCommentFeedback(String rejectionCommentFeedback) { + this.rejectionCommentFeedback = rejectionCommentFeedback; + } + + public String getMotivation() { + return motivation; + } + + public void setMotivation(String motivation) { + this.motivation = motivation; + } + + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- public List<GradingCriterion> getProjectCriteria() { List<GradingCriterion> result = new ArrayList<>(); for (GradingCriterion criterion : getGradingCriteria()) { @@ -82,34 +125,6 @@ public class SupervisorGradingReport extends GradingReport { return true; } - public User getUser() { - return this.user; - } - - public String getRejectionComment() { - return rejectionComment; - } - - public void setRejectionComment(String rejectionComment) { - this.rejectionComment = rejectionComment; - } - - public String getRejectionCommentFeedback() { - return rejectionCommentFeedback; - } - - public void setRejectionCommentFeedback(String rejectionCommentFeedback) { - this.rejectionCommentFeedback = rejectionCommentFeedback; - } - - public String getMotivation() { - return motivation; - } - - public void setMotivation(String motivation) { - this.motivation = motivation; - } - public boolean hasProvidedOverallMotivation() { return getMotivation() != null && !getMotivation().isBlank(); } diff --git a/core/src/main/java/se/su/dsv/scipro/reviewing/Decision.java b/core/src/main/java/se/su/dsv/scipro/reviewing/Decision.java index cc255a893e..6d3fb25f16 100644 --- a/core/src/main/java/se/su/dsv/scipro/reviewing/Decision.java +++ b/core/src/main/java/se/su/dsv/scipro/reviewing/Decision.java @@ -20,51 +20,73 @@ import se.su.dsv.scipro.system.User; import java.time.Instant; import java.time.LocalDate; -import java.util.*; +import java.util.Date; +import java.util.Optional; @Entity -@Table(name = "Decision") +@Table(name = "decision") public class Decision { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Basic + @Column(name = "status") @Enumerated(EnumType.STRING) private Status status = Status.UNDECIDED; - @OneToOne(optional = false) - @JoinColumn(name = "thesis_reference_id") - private FileReference thesis; - @Basic + @Column(name = "reason") private String reason; @Basic + @Column(name = "comment") private String comment; - @OneToOne(optional = true) - @JoinColumn(name = "attachment_reference_id") - private FileReference attachment; - + @Basic + @Column(name = "requested_date") @Temporal(TemporalType.TIMESTAMP) private Date requested; - @Temporal(TemporalType.TIMESTAMP) - private Date deadline; - + @Basic + @Column(name = "decision_date") @Temporal(TemporalType.TIMESTAMP) private Date decisionDate; - @ManyToOne(optional = false) - private ReviewerApproval reviewerApproval; - - @ManyToOne - @JoinColumn(name = "assigned_reviewer_id") - private User assignedReviewer; + @Basic + @Column(name = "deadline") + @Temporal(TemporalType.TIMESTAMP) + private Date deadline; + @Basic @Column(name = "assigned_reviewer_date") private LocalDate reviewerAssignedAt; + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (decision) referencing other tables. + // ---------------------------------------------------------------------------------- + @ManyToOne + @JoinColumn(name = "assigned_reviewer_id", referencedColumnName = "id") + private User assignedReviewer; + + @OneToOne(optional = true) + @JoinColumn(name = "attachment_reference_id", referencedColumnName = "id") + private FileReference attachment; + + @ManyToOne(optional = false) + @JoinColumn(name = "reviewer_approval_id", referencedColumnName = "id") + private ReviewerApproval reviewerApproval; + + @OneToOne(optional = false) + @JoinColumn(name = "thesis_reference_id", referencedColumnName = "id") + private FileReference thesis; + + // ---------------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------------- protected Decision() {} // JPA Decision(ReviewerApproval reviewerApproval, final FileReference thesis, final String comment, final Date deadline) { @@ -79,6 +101,9 @@ public class Decision { this.comment = comment; } + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- public Long getId() { return id; } @@ -87,14 +112,6 @@ public class Decision { this.id = id; } - public FileReference getThesis() { - return thesis; - } - - public ReviewerApproval getReviewerApproval() { - return reviewerApproval; - } - public Status getStatus() { return status; } @@ -107,10 +124,6 @@ public class Decision { return comment; } - public Optional<FileReference> getAttachment() { - return Optional.ofNullable(attachment); - } - public Date getRequested() { return requested; } @@ -127,14 +140,6 @@ public class Decision { this.deadline = deadline; } - public User getAssignedReviewer() { - return assignedReviewer; - } - - public void setAssignedReviewer(User assignedReviewer) { - this.assignedReviewer = assignedReviewer; - } - public LocalDate getReviewerAssignedAt() { return reviewerAssignedAt; } @@ -143,6 +148,29 @@ public class Decision { this.reviewerAssignedAt = reviewerAssignedAt; } + public User getAssignedReviewer() { + return assignedReviewer; + } + + public void setAssignedReviewer(User assignedReviewer) { + this.assignedReviewer = assignedReviewer; + } + + public Optional<FileReference> getAttachment() { + return Optional.ofNullable(attachment); + } + + public ReviewerApproval getReviewerApproval() { + return reviewerApproval; + } + + public FileReference getThesis() { + return thesis; + } + + // ---------------------------------------------------------------------------------- + // Other methods + // ---------------------------------------------------------------------------------- void approve(final String reason, final Optional<FileReference> attachment) { decide(Status.APPROVED, reason, attachment); } diff --git a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerApproval.java b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerApproval.java index 25c63338aa..cdad680797 100644 --- a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerApproval.java +++ b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerApproval.java @@ -1,6 +1,8 @@ package se.su.dsv.scipro.reviewing; import jakarta.persistence.GenerationType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Table; import se.su.dsv.scipro.file.FileReference; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.DomainObject; @@ -13,31 +15,61 @@ import jakarta.persistence.Id; import jakarta.persistence.OneToMany; import jakarta.persistence.OneToOne; import jakarta.persistence.OrderBy; -import java.util.*; + +import java.util.Collections; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; @Entity +@Table(name = "reviewer_approval") @DiscriminatorColumn(name = "type", length = 64) public abstract class ReviewerApproval extends DomainObject { - @OneToOne(optional = false) - protected Project project; - - @OneToMany(mappedBy = "reviewerApproval", cascade = CascadeType.ALL) - @OrderBy("requested desc") - protected List<Decision> decisions = new LinkedList<>(); - + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - public abstract Step getStep(); + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (reviewer_approval) referencing other + // tables. + // ---------------------------------------------------------------------------------- + @OneToOne(optional = false) + @JoinColumn(name = "project_id", referencedColumnName = "id") + protected Project project; - public FileReference getCurrentThesis() { - return getCurrentDecision().getThesis(); + // ---------------------------------------------------------------------------------- + // JPA-mappings of other tables referencing to this table "reviewer_approval" + // ---------------------------------------------------------------------------------- + @OneToMany(mappedBy = "reviewerApproval", cascade = CascadeType.ALL) + @OrderBy("requested desc") + protected List<Decision> decisions = new LinkedList<>(); + + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- + @Override + public Long getId() { + return this.id; } public Project getProject(){return this.project;} + // ---------------------------------------------------------------------------------- + // Other methods + // ---------------------------------------------------------------------------------- + public abstract Step getStep(); + public Decision getCurrentDecision() { + return decisions.get(0); + } + + public FileReference getCurrentThesis() { + return getCurrentDecision().getThesis(); + } public Status getCurrentStatus() { return getCurrentDecision().getStatus(); @@ -63,10 +95,6 @@ public abstract class ReviewerApproval extends DomainObject { getCurrentDecision().reject(reason, attachment); } - public Decision getCurrentDecision() { - return decisions.get(0); - } - public void addNewThesis(final FileReference thesis, final String comment, final Date deadline) { if (getCurrentStatus() != Status.REJECTED) { throw new IllegalStateException(); @@ -86,17 +114,15 @@ public abstract class ReviewerApproval extends DomainObject { return getCurrentStatus() == Status.APPROVED; } - @Override - public Long getId() { - return this.id; + public Date getCurrentDeadline() { + return getCurrentDecision().getDeadline(); } + // ---------------------------------------------------------------------------------- + // Nested types. + // ---------------------------------------------------------------------------------- public enum Step { ROUGH_DRAFT_APPROVAL, FINAL_SEMINAR_APPROVAL } - - public Date getCurrentDeadline() { - return getCurrentDecision().getDeadline(); - } } diff --git a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerDeadlineSettings.java b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerDeadlineSettings.java index 3b200eac44..044ada8fb5 100644 --- a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerDeadlineSettings.java +++ b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerDeadlineSettings.java @@ -13,13 +13,13 @@ public class ReviewerDeadlineSettings extends DomainObject { @Id private Long id = null; - @Basic(optional = false) + @Column(name = "rough_draft_approval", nullable = false) private int roughDraftApproval = 5; - @Basic(optional = false) + @Column(name = "final_seminar_approval", nullable = false) private int finalSeminarApproval = 2; - @Basic(optional = false) + @Column(name = "final_grading", nullable = false) private int finalGrading = 5; public ReviewerDeadlineSettings() { diff --git a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerTarget.java b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerTarget.java index 4a8b145f2e..29803d920f 100644 --- a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerTarget.java +++ b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerTarget.java @@ -1,5 +1,6 @@ package se.su.dsv.scipro.reviewing; +import jakarta.persistence.Basic; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -10,7 +11,6 @@ import jakarta.persistence.Table; import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.User; -import java.time.LocalDate; import java.util.Objects; @Entity @@ -20,22 +20,26 @@ public class ReviewerTarget extends DomainObject { @GeneratedValue(strategy = jakarta.persistence.GenerationType.IDENTITY) private Long id; - @ManyToOne(optional = false) - @JoinColumn(name = "reviewer_id", nullable = false) - private User reviewer; - + @Basic @Column(name = "year", nullable = false) private int year; + @Basic @Column(name = "spring", nullable = false) private int spring; + @Basic @Column(name = "autumn", nullable = false) private int autumn; + @Basic @Column(name = "note") private String note; + @ManyToOne(optional = false) + @JoinColumn(name = "reviewer_user_id", referencedColumnName = "id", nullable = false) + private User reviewer; + @Override public Long getId() { return id; diff --git a/core/src/main/java/se/su/dsv/scipro/settings/dataobjects/UserProfile.java b/core/src/main/java/se/su/dsv/scipro/settings/dataobjects/UserProfile.java index ac863a2afa..e88c4b289b 100644 --- a/core/src/main/java/se/su/dsv/scipro/settings/dataobjects/UserProfile.java +++ b/core/src/main/java/se/su/dsv/scipro/settings/dataobjects/UserProfile.java @@ -1,5 +1,26 @@ package se.su.dsv.scipro.settings.dataobjects; +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumSet; +import java.util.Objects; + +import jakarta.persistence.Basic; +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; + import se.su.dsv.scipro.project.ProjectStatus; import se.su.dsv.scipro.project.ProjectTeamMemberRoles; import se.su.dsv.scipro.security.auth.roles.Roles; @@ -7,12 +28,6 @@ import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.ProjectType; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; -import java.util.ArrayList; -import java.util.Collection; -import java.util.EnumSet; -import java.util.Objects; - @Entity @Table(name = "user_profile") public class UserProfile extends DomainObject { @@ -24,40 +39,46 @@ public class UserProfile extends DomainObject { @OneToOne(optional = false) private User user; - @Basic(optional = true) - private String skypeId; - - @Basic(optional = true) - private String phoneNumber; - - @Basic(optional = true) + @Column(name = "other_info", nullable = true) private String otherInfo; - @Basic(optional = false) + @Column(name = "phone_number", nullable = true) + private String phoneNumber; + + @Column(name = "skype_id", nullable = true) + private String skypeId; + + @Column(name = "mail_compilation", nullable = false) private boolean mailCompilation = false; + @Column(name = "default_supervisor_filter", nullable = false) + private boolean defaultSupervisorFilter = true; + + @Enumerated(EnumType.STRING) + @Column(name = "selected_role") + private Roles selectedRole; + @ElementCollection @Enumerated(EnumType.STRING) + @CollectionTable(name = "user_profile_default_project_status_filter", + joinColumns = @JoinColumn(name = "user_profile_id", referencedColumnName = "id")) + @Column(name = "default_project_status_filter") private Collection<ProjectStatus> defaultProjectStatusFilter = EnumSet.of(ProjectStatus.ACTIVE); @ElementCollection @Enumerated(EnumType.STRING) + @CollectionTable(name = "user_profile_default_project_team_member_roles_filter", + joinColumns = @JoinColumn(name = "user_profile_id", referencedColumnName = "id")) + @Column(name = "default_project_team_member_roles_filter") private Collection<ProjectTeamMemberRoles> defaultProjectTeamMemberRolesFilter = EnumSet.of(ProjectTeamMemberRoles.CO_SUPERVISOR); - @Basic(optional = false) - private boolean defaultSupervisorFilter = true; - @ManyToMany - @JoinTable( - name = "user_profile_ProjectType", - joinColumns = {@JoinColumn(name = "user_profile_id")} + @JoinTable(name = "user_profile_project_type", + joinColumns = @JoinColumn(name = "user_profile_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "project_type_id", referencedColumnName = "id") ) private Collection<ProjectType> defaultProjectTypeFilter = new ArrayList<>(); - @Basic - @Enumerated(EnumType.STRING) - private Roles selectedRole; - @Basic @Enumerated(EnumType.STRING) @Column(name = "supervisor_project_note_display") diff --git a/core/src/main/java/se/su/dsv/scipro/survey/Question.java b/core/src/main/java/se/su/dsv/scipro/survey/Question.java index 4097ad1283..4c2d6e4a73 100644 --- a/core/src/main/java/se/su/dsv/scipro/survey/Question.java +++ b/core/src/main/java/se/su/dsv/scipro/survey/Question.java @@ -1,11 +1,23 @@ package se.su.dsv.scipro.survey; -import jakarta.persistence.*; +import jakarta.persistence.Basic; +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Table; + import java.io.Serializable; import java.util.LinkedList; import java.util.List; @Entity +@Table(name = "question") public class Question implements Serializable { public enum Type { TEXT, SINGLE_CHOICE, MULTIPLE_CHOICE, GROUP_HEADING } @@ -20,6 +32,9 @@ public class Question implements Serializable { private String text; @ElementCollection(fetch = FetchType.EAGER) + @CollectionTable(name = "question_choices", + joinColumns = @JoinColumn(name = "question_id", referencedColumnName = "id")) + @Column(name = "choices") private List<String> choices = new LinkedList<>(); private Type type = Type.TEXT; diff --git a/core/src/main/java/se/su/dsv/scipro/survey/Survey.java b/core/src/main/java/se/su/dsv/scipro/survey/Survey.java index 01b44b7e1d..9c9621ec02 100644 --- a/core/src/main/java/se/su/dsv/scipro/survey/Survey.java +++ b/core/src/main/java/se/su/dsv/scipro/survey/Survey.java @@ -1,14 +1,23 @@ package se.su.dsv.scipro.survey; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.io.Serializable; import java.util.LinkedList; import java.util.List; @Entity +@Table(name = "survey") public class Survey implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/core/src/main/java/se/su/dsv/scipro/survey/SurveyAnswer.java b/core/src/main/java/se/su/dsv/scipro/survey/SurveyAnswer.java index 0deab2b69b..f8d94e7ab9 100644 --- a/core/src/main/java/se/su/dsv/scipro/survey/SurveyAnswer.java +++ b/core/src/main/java/se/su/dsv/scipro/survey/SurveyAnswer.java @@ -6,7 +6,7 @@ import java.util.Set; import java.util.TreeSet; @Entity -@Table +@Table(name = "survey_answer") public class SurveyAnswer implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -21,6 +21,9 @@ public class SurveyAnswer implements Serializable { private String answer; @ElementCollection(fetch = FetchType.EAGER) + @CollectionTable(name = "survey_answer_multiple_answers", + joinColumns = @JoinColumn(name = "survey_answer_id", referencedColumnName = "id")) + @Column(name = "multiple_answers") private Set<String> multipleAnswers = new TreeSet<>(); public Survey getSurvey() { diff --git a/core/src/main/java/se/su/dsv/scipro/system/DomainObject.java b/core/src/main/java/se/su/dsv/scipro/system/DomainObject.java index bb414d678c..ebcdbb5627 100755 --- a/core/src/main/java/se/su/dsv/scipro/system/DomainObject.java +++ b/core/src/main/java/se/su/dsv/scipro/system/DomainObject.java @@ -8,10 +8,10 @@ import java.util.Objects; @MappedSuperclass public abstract class DomainObject implements Serializable { - @Basic(optional=false) + @Column(name = "date_created", nullable = false) private Date dateCreated = new Date(); - @Basic(optional = false) + @Column(name = "last_modified", nullable = false) private Date lastModified = new Date(); @Version diff --git a/core/src/main/java/se/su/dsv/scipro/system/Event.java b/core/src/main/java/se/su/dsv/scipro/system/Event.java index 76abc8f2bb..be417ccb9a 100644 --- a/core/src/main/java/se/su/dsv/scipro/system/Event.java +++ b/core/src/main/java/se/su/dsv/scipro/system/Event.java @@ -1,22 +1,36 @@ package se.su.dsv.scipro.system; import jakarta.persistence.Basic; +import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.Id; +import jakarta.persistence.Table; + import java.io.Serializable; import java.util.Objects; @Entity +@Table(name = "event") public class Event implements Serializable { + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- @Id private String name; @Basic + @Column(name = "description") private String description; + // ---------------------------------------------------------------------------------- + // Constructor + // ---------------------------------------------------------------------------------- protected Event() { } + // ---------------------------------------------------------------------------------- + // Properties (Getters) + // ---------------------------------------------------------------------------------- public String getName() { return this.name; } @@ -25,6 +39,13 @@ public class Event implements Serializable { return this.description; } + // ---------------------------------------------------------------------------------- + // Other Methods + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof Event; + } + @Override public boolean equals(final Object o) { if (o == this) return true; @@ -34,10 +55,6 @@ public class Event implements Serializable { && Objects.equals(this.getName(), other.getName()); } - protected boolean canEqual(final Object other) { - return other instanceof Event; - } - @Override public int hashCode() { return Objects.hashCode(this.getName()); @@ -45,6 +62,7 @@ public class Event implements Serializable { @Override public String toString() { - return "Event(name=" + this.getName() + ", description=" + this.getDescription() + ")"; + return "Event(name=" + this.getName() + ", description=" + + this.getDescription() + ")"; } } diff --git a/core/src/main/java/se/su/dsv/scipro/system/ExternalResource.java b/core/src/main/java/se/su/dsv/scipro/system/ExternalResource.java index 852eac7bbb..008e47babe 100644 --- a/core/src/main/java/se/su/dsv/scipro/system/ExternalResource.java +++ b/core/src/main/java/se/su/dsv/scipro/system/ExternalResource.java @@ -1,9 +1,18 @@ package se.su.dsv.scipro.system; -import jakarta.persistence.*; +import jakarta.persistence.Basic; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; + import java.util.Objects; @Entity +@Table(name = "external_resource") public class ExternalResource { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -16,6 +25,7 @@ public class ExternalResource { private String url; @ManyToOne(optional = false) + @JoinColumn(name = "project_type_id") private ProjectType relevantFor; public ExternalResource() {} // JPA diff --git a/core/src/main/java/se/su/dsv/scipro/system/FooterLink.java b/core/src/main/java/se/su/dsv/scipro/system/FooterLink.java index 7676611142..68a84f622f 100644 --- a/core/src/main/java/se/su/dsv/scipro/system/FooterLink.java +++ b/core/src/main/java/se/su/dsv/scipro/system/FooterLink.java @@ -13,6 +13,7 @@ public class FooterLink extends DomainObject { private Long id; @Enumerated(EnumType.STRING) + @Column(name = "footer_column") private FooterColumn footerColumn; @Basic(optional = false) diff --git a/core/src/main/java/se/su/dsv/scipro/system/Password.java b/core/src/main/java/se/su/dsv/scipro/system/Password.java index 32dd434660..8cc600ed24 100755 --- a/core/src/main/java/se/su/dsv/scipro/system/Password.java +++ b/core/src/main/java/se/su/dsv/scipro/system/Password.java @@ -1,11 +1,18 @@ package se.su.dsv.scipro.system; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; + import java.util.Arrays; import java.util.Objects; @Entity -@Table +@Table(name = "password") public class Password extends LazyDeletableDomainObject { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/core/src/main/java/se/su/dsv/scipro/system/Program.java b/core/src/main/java/se/su/dsv/scipro/system/Program.java index 2c23655ccc..f2aba4587d 100644 --- a/core/src/main/java/se/su/dsv/scipro/system/Program.java +++ b/core/src/main/java/se/su/dsv/scipro/system/Program.java @@ -1,10 +1,16 @@ package se.su.dsv.scipro.system; -import jakarta.persistence.*; import java.util.Objects; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + @Entity -@Table(name = "Program") +@Table(name = "program") public class Program extends DomainObject { @Id @@ -12,13 +18,13 @@ public class Program extends DomainObject { @Column(name = "id") private Long id; - @Column(name = "externalId") + @Column(name = "external_id") private Integer externalId; - @Column(name = "name") + @Column(name = "name_sv") private String name; - @Column(name = "nameEn", nullable = true) + @Column(name = "name_en", nullable = true) private String nameEn; @Column(name = "code") diff --git a/core/src/main/java/se/su/dsv/scipro/system/ProjectType.java b/core/src/main/java/se/su/dsv/scipro/system/ProjectType.java index 0d3bd00f2c..b3f8849870 100644 --- a/core/src/main/java/se/su/dsv/scipro/system/ProjectType.java +++ b/core/src/main/java/se/su/dsv/scipro/system/ProjectType.java @@ -1,12 +1,29 @@ package se.su.dsv.scipro.system; -import jakarta.persistence.*; import java.util.EnumSet; import java.util.Objects; import java.util.Set; +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.CascadeType; +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Lob; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; + @Entity @Cacheable(true) +@Table(name = "project_type") public class ProjectType extends LazyDeletableDomainObject { public static final DegreeType MASTER = DegreeType.MASTER; public static final DegreeType BACHELOR = DegreeType.BACHELOR; @@ -26,7 +43,7 @@ public class ProjectType extends LazyDeletableDomainObject { private ProjectTypeSettings projectTypeSettings = new ProjectTypeSettings(this); @Enumerated(EnumType.STRING) - @Column(nullable = false) + @Column(name = "degree_type", nullable = false) private DegreeType degreeType = DegreeType.NONE; @Lob @@ -34,7 +51,9 @@ public class ProjectType extends LazyDeletableDomainObject { @ElementCollection @Enumerated(EnumType.STRING) - @JoinTable(name = "project_type_project_modules") + @CollectionTable(name = "project_type_project_module", + joinColumns = @JoinColumn(name = "project_type_id", referencedColumnName = "id")) + @Column(name = "project_module") private Set<ProjectModule> projectModules = EnumSet.allOf(ProjectModule.class); @Basic(optional = false) diff --git a/core/src/main/java/se/su/dsv/scipro/system/ProjectTypeSettings.java b/core/src/main/java/se/su/dsv/scipro/system/ProjectTypeSettings.java index f83d626f1b..2c64d6629d 100755 --- a/core/src/main/java/se/su/dsv/scipro/system/ProjectTypeSettings.java +++ b/core/src/main/java/se/su/dsv/scipro/system/ProjectTypeSettings.java @@ -1,68 +1,84 @@ package se.su.dsv.scipro.system; -import jakarta.persistence.*; +import jakarta.persistence.Cacheable; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; + import java.util.Objects; @Entity -@Table(name="project_type_settings") @Cacheable(true) +@Table(name="project_type_settings") public class ProjectTypeSettings extends DomainObject { - public ProjectTypeSettings(){} - - public ProjectTypeSettings(ProjectType projectType){ - this.projectType = projectType; - } + public static final int DEFAULT_NUM_DAYS_BETWEEN_REVIEWS_ON_SAME_PROJECT = 7; + public static final int DEFAULT_NUM_DAYS_TO_SUBMIT_PEER_REVIEW = 3; + public static final int DEFAULT_NUM_DAYS_BEFORE_CANCELLED_PEERS = 90; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @OneToOne(optional = false) + @JoinColumn(name = "project_type_id") private ProjectType projectType; - @Basic(optional=false) - private int minAuthors = 1; - @Basic(optional=false) - private int maxAuthors = 2; - - @Basic(optional=false) - private int maxFinalSeminarActiveParticipation; - @Basic(optional=false) - private int maxOpponentsOnFinalSeminar; - @Basic(optional=false) - private int minFinalSeminarActiveParticipation; - @Basic(optional=false) - private int minOpponentsOnFinalSeminar; - - private int minimumOppositionsToBeGraded = 0; - private int minimumActiveParticipationsToBeGraded = 0; - - public static final int DEFAULT_NUM_DAYS_BETWEEN_REVIEWS_ON_SAME_PROJECT = 7; - public static final int DEFAULT_NUM_DAYS_TO_SUBMIT_PEER_REVIEW = 3; - public static final int DEFAULT_NUM_DAYS_BEFORE_CANCELLED_PEERS = 90; - /* * Defines the time span between reviews on the same project */ - @Basic(optional = false) + @Column(name = "num_days_between_peer_reviews_on_same_project", nullable = false) private int numDaysBetweenPeerReviewsOnSameProject = DEFAULT_NUM_DAYS_BETWEEN_REVIEWS_ON_SAME_PROJECT; - + /* * Defines the number of days between accepting a review and the deadline for review submission */ - @Basic(optional = false) + @Column(name = "num_days_to_submit_peer_review", nullable = false) private int numDaysToSubmitPeerReview = DEFAULT_NUM_DAYS_TO_SUBMIT_PEER_REVIEW; /* * Defines the number of days between accepting a review and the deadline for review submission */ - @Basic(optional = false) + @Column(name = "num_days_before_peer_gets_cancelled", nullable = false) private int numDaysBeforePeerGetsCancelled = DEFAULT_NUM_DAYS_BEFORE_CANCELLED_PEERS; - @Basic + @Column(name = "min_authors", nullable = false) + private int minAuthors = 1; + + @Column(name = "max_authors", nullable = false) + private int maxAuthors = 2; + + @Column(name = "max_final_seminar_active_participation", nullable = false) + private int maxFinalSeminarActiveParticipation; + + @Column(name = "max_opponents_on_final_seminar", nullable = false) + private int maxOpponentsOnFinalSeminar; + + @Column(name = "min_final_seminar_active_participation", nullable = false) + private int minFinalSeminarActiveParticipation; + + @Column(name = "min_opponents_on_final_seminar", nullable = false) + private int minOpponentsOnFinalSeminar; + + @Column(name = "min_oppositions_to_be_graded") + private int minOppositionsToBeGraded = 0; + + @Column(name = "min_active_participations_to_be_graded") + private int minActiveParticipationsToBeGraded = 0; + @Column(name = "review_process_information_url_for_supervisor") private String reviewProcessInformationUrl; + public ProjectTypeSettings(){} + + public ProjectTypeSettings(ProjectType projectType){ + this.projectType = projectType; + } + @Override public Long getId() { return this.id; @@ -152,20 +168,20 @@ public class ProjectTypeSettings extends DomainObject { this.numDaysBeforePeerGetsCancelled = numDaysBeforePeerGetsCancelled; } - public int getMinimumOppositionsToBeGraded() { - return minimumOppositionsToBeGraded; + public int getMinOppositionsToBeGraded() { + return minOppositionsToBeGraded; } - public void setMinimumOppositionsToBeGraded(int minimumOppositionsToBeGraded) { - this.minimumOppositionsToBeGraded = minimumOppositionsToBeGraded; + public void setMinOppositionsToBeGraded(int minimumOppositionsToBeGraded) { + this.minOppositionsToBeGraded = minimumOppositionsToBeGraded; } - public int getMinimumActiveParticipationsToBeGraded() { - return minimumActiveParticipationsToBeGraded; + public int getMinActiveParticipationsToBeGraded() { + return minActiveParticipationsToBeGraded; } - public void setMinimumActiveParticipationsToBeGraded(int minimumActiveParticipationsToBeGraded) { - this.minimumActiveParticipationsToBeGraded = minimumActiveParticipationsToBeGraded; + public void setMinActiveParticipationsToBeGraded(int minimumActiveParticipationsToBeGraded) { + this.minActiveParticipationsToBeGraded = minimumActiveParticipationsToBeGraded; } public String getReviewProcessInformationUrl() { diff --git a/core/src/main/java/se/su/dsv/scipro/system/ResearchArea.java b/core/src/main/java/se/su/dsv/scipro/system/ResearchArea.java index 11a8bb041f..01e994645b 100755 --- a/core/src/main/java/se/su/dsv/scipro/system/ResearchArea.java +++ b/core/src/main/java/se/su/dsv/scipro/system/ResearchArea.java @@ -1,14 +1,22 @@ package se.su.dsv.scipro.system; -import jakarta.persistence.*; +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + import java.util.Objects; @Entity -@Table(name = "researcharea") +@Table(name = "research_area") @Cacheable(true) public class ResearchArea extends LazyDeletableDomainObject { - public static final int STRING_MAX_LENGTH = 255; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; diff --git a/core/src/main/java/se/su/dsv/scipro/system/Unit.java b/core/src/main/java/se/su/dsv/scipro/system/Unit.java index acc2b2793c..404baee063 100755 --- a/core/src/main/java/se/su/dsv/scipro/system/Unit.java +++ b/core/src/main/java/se/su/dsv/scipro/system/Unit.java @@ -1,6 +1,13 @@ package se.su.dsv.scipro.system; -import jakarta.persistence.*; +import jakarta.persistence.Cacheable; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + import java.util.Objects; @Entity @@ -17,11 +24,10 @@ public class Unit extends DomainObject { @Column(unique = true) private Integer identifier; - @Column(length = STRING_MAX_LENGTH) - @Basic(optional = false) + @Column(nullable = false, length = STRING_MAX_LENGTH) private String title; - @Basic(optional = true) + @Column(name = "match_responsible", nullable = true) private String matchResponsible; public String getMatchResponsible() { diff --git a/core/src/main/java/se/su/dsv/scipro/system/User.java b/core/src/main/java/se/su/dsv/scipro/system/User.java index 1ee2da3877..9addbde052 100755 --- a/core/src/main/java/se/su/dsv/scipro/system/User.java +++ b/core/src/main/java/se/su/dsv/scipro/system/User.java @@ -1,10 +1,32 @@ package se.su.dsv.scipro.system; -import se.su.dsv.scipro.security.auth.roles.Roles; +import jakarta.persistence.Basic; +import jakarta.persistence.Cacheable; +import jakarta.persistence.CascadeType; +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; -import jakarta.persistence.*; import java.io.Serializable; -import java.util.*; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import se.su.dsv.scipro.security.auth.roles.Roles; @Entity @Table(name = "user") @@ -18,9 +40,10 @@ public class User extends LazyDeletableDomainObject { @Column(unique = true) private Integer identifier; - @Basic(optional = false) + @Column(name = "first_name", nullable = false) private String firstName; - @Basic(optional = false) + + @Column(name = "last_name", nullable = false) private String lastName; // Mapped to a generated column to allow sorting UserColumn in DataTables @@ -35,14 +58,15 @@ public class User extends LazyDeletableDomainObject { // If you wish to test specific sort orders then add specific methods that sort // by firstName, lastName instead. @SuppressWarnings("unused") - @Basic - @Column(insertable = false, updatable = false) + @Column(name = "full_name", insertable = false, updatable = false) private String fullName; - @Basic(optional = false) + @Column(name = "email_address", nullable = false) private String emailAddress; + @Basic(optional = false) private boolean deceased = false; + @Basic(optional = false) @Column(name = "active_as_supervisor") private boolean activeAsSupervisor = false; @@ -64,20 +88,22 @@ public class User extends LazyDeletableDomainObject { private Set<Program> programs = new HashSet<>(); @ElementCollection - @CollectionTable(name = "user_languages") + @CollectionTable(name = "user_language") @Column(name = "language") @Enumerated(EnumType.STRING) private Set<Language> languages = EnumSet.noneOf(Language.class); @ManyToMany - @JoinTable(name = "user_research_area", inverseJoinColumns = @JoinColumn(name = "research_area_id")) + @JoinTable(name = "user_research_area", + joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "research_area_id", referencedColumnName = "id")) private Set<ResearchArea> researchAreas = new HashSet<>(); @OneToOne(optional = true) private Unit unit; - @Basic @Enumerated(EnumType.STRING) + @Column(name = "degree_type") private DegreeType degreeType = ProjectType.UNKNOWN; public Unit getUnit() { diff --git a/core/src/main/java/se/su/dsv/scipro/system/Username.java b/core/src/main/java/se/su/dsv/scipro/system/Username.java index e4836b5070..5da461d2b6 100755 --- a/core/src/main/java/se/su/dsv/scipro/system/Username.java +++ b/core/src/main/java/se/su/dsv/scipro/system/Username.java @@ -1,17 +1,26 @@ package se.su.dsv.scipro.system; -import jakarta.persistence.*; +import jakarta.persistence.Cacheable; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; + import java.util.Objects; @Entity +@Table(name="username", uniqueConstraints={@UniqueConstraint(name = "uk_username", columnNames={"username"})}) @Cacheable(true) -@Table(name="username", uniqueConstraints={@UniqueConstraint(columnNames={"username"})}) public class Username extends DomainObject { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Basic(optional=false) + @Column(name = "username", nullable = false) private String username; @ManyToOne(optional=false) diff --git a/core/src/main/java/se/su/dsv/scipro/thesislink/ExternalLink.java b/core/src/main/java/se/su/dsv/scipro/thesislink/ExternalLink.java index aeeff1631a..ee96eb8884 100644 --- a/core/src/main/java/se/su/dsv/scipro/thesislink/ExternalLink.java +++ b/core/src/main/java/se/su/dsv/scipro/thesislink/ExternalLink.java @@ -1,84 +1,103 @@ package se.su.dsv.scipro.thesislink; +import jakarta.persistence.Basic; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.User; -import jakarta.persistence.*; import java.util.Objects; @Entity -@Table(name = "externallink") +@Table(name = "external_link") public class ExternalLink extends DomainObject { public static final int MAX_CHARS = 255; - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(optional = false) - private Project project; - - @Column(nullable = false, length = MAX_CHARS) - private String url = ""; - - @ManyToOne(optional = false) - private User user; - - @Column(nullable = true, length = MAX_CHARS) - private String description = ""; - public static IProject builder() { return new Builder(); } + // ---------------------------------------------------------------------------------- + // Basic JPA-mappings + // ---------------------------------------------------------------------------------- + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Basic + @Column(name = "url", nullable = false, length = MAX_CHARS) + private String url = ""; + + @Column(name = "description", nullable = true, length = MAX_CHARS) + private String description = ""; + + // ---------------------------------------------------------------------------------- + // JPA-mappings of foreign keys in this table (external_link) referencing + // other tables. + // ---------------------------------------------------------------------------------- + @ManyToOne(optional = false) + @JoinColumn(name = "project_id", referencedColumnName = "id") + private Project project; + + @ManyToOne(optional = false) + @JoinColumn(name = "user_id", referencedColumnName = "id") + private User user; + + // ---------------------------------------------------------------------------------- + // Properties (Getters and Setters) + // ---------------------------------------------------------------------------------- @Override public Long getId() { return this.id; } - public Project getProject() { - return this.project; - } - - public String getUrl() { - return this.url; - } - - public User getUser() { - return this.user; - } - - public String getDescription() { - return this.description; - } - public void setId(Long id) { this.id = id; } - public void setProject(Project project) { - this.project = project; + public String getUrl() { + return this.url; } public void setUrl(String url) { this.url = url; } - public void setUser(User user) { - this.user = user; + public String getDescription() { + return this.description; } public void setDescription(String description) { this.description = description; } - @Override - public String toString() { - return "ExternalLink(id=" + this.getId() + ", project=" + this.getProject() + ", url=" + this.getUrl() + ", user=" + this.getUser() + ", description=" + this.getDescription() + ")"; + public Project getProject() { + return this.project; } + public void setProject(Project project) { + this.project = project; + } + + public User getUser() { + return this.user; + } + + public void setUser(User user) { + this.user = user; + } + + // ---------------------------------------------------------------------------------- + // Methods Common To All Objects + // ---------------------------------------------------------------------------------- @Override public boolean equals(final Object o) { if (o == this) return true; @@ -92,15 +111,28 @@ public class ExternalLink extends DomainObject { && Objects.equals(this.getDescription(), other.getDescription()); } - protected boolean canEqual(final Object other) { - return other instanceof ExternalLink; - } - @Override public int hashCode() { return Objects.hash(this.getId(), this.getProject(), this.getUrl(), this.getUser(), this.getDescription()); } + @Override + public String toString() { + return "ExternalLink(id=" + this.getId() + ", project=" + this.getProject() + + ", url=" + this.getUrl() + ", user=" + this.getUser() + ", description=" + + this.getDescription() + ")"; + } + + // ---------------------------------------------------------------------------------- + // Other method + // ---------------------------------------------------------------------------------- + protected boolean canEqual(final Object other) { + return other instanceof ExternalLink; + } + + // ---------------------------------------------------------------------------------- + // Nested types + // ---------------------------------------------------------------------------------- private static class Builder implements IProject, IURL, IUser, IBuild { private ExternalLink instance = new ExternalLink(); diff --git a/core/src/main/java/se/su/dsv/scipro/workerthreads/WorkerData.java b/core/src/main/java/se/su/dsv/scipro/workerthreads/WorkerData.java index 4827139331..59fefc8d63 100755 --- a/core/src/main/java/se/su/dsv/scipro/workerthreads/WorkerData.java +++ b/core/src/main/java/se/su/dsv/scipro/workerthreads/WorkerData.java @@ -7,7 +7,7 @@ import java.util.Date; import java.util.Objects; @Entity -@Table(name="worker_data") +@Table(name = "worker_data") @Cacheable(true) public class WorkerData extends DomainObject { public WorkerData() { @@ -18,13 +18,13 @@ public class WorkerData extends DomainObject { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(unique=true, nullable=false) + @Column(unique = true, nullable = false) private String name; - @Column(nullable=false) - private Date lastRun=new Date(); + @Column(nullable = false, name = "last_run") + private Date lastRun = new Date(); - @Column(nullable=false) + @Column(nullable = false, name = "last_successful_run") private Date lastSuccessfulRun; @PreUpdate diff --git a/core/src/main/resources/db/migration/V391__harmonize_table_attribute_name.sql b/core/src/main/resources/db/migration/V391__harmonize_table_attribute_name.sql new file mode 100644 index 0000000000..15c116c0ff --- /dev/null +++ b/core/src/main/resources/db/migration/V391__harmonize_table_attribute_name.sql @@ -0,0 +1,3222 @@ +/* + * Step 1: Remove obsolete tables + */ + +drop table plugin_settings; +drop table turnitincheck; + +alter table TurnitinSettings_expirationMails drop foreign key FK_lji32bekgobx76otvw7syu4hb; +drop table TurnitinSettings_expirationMails; + +drop table TurnitinSettings; + +/* + * Step 2: DomainObject related classes and tables. + * + * Many entity classes inherit directly or indirectly from abstract super class DomainObject. Two attributes + * dateCreated and lastModified, have changed mapping to column name with snake case, date_created and last_modified. + * This change affects many, many tables, which are to be managed at first. + */ + +-- table: ActivityPlan + +alter table `ActivityPlan` rename column `dateCreated` to `date_created`; +alter table `ActivityPlan` rename column `lastModified` to `last_modified`; + +-- table: ActivityPlanTemplate + +alter table `ActivityPlanTemplate` rename column `dateCreated` to `date_created`; +alter table `ActivityPlanTemplate` rename column `lastModified` to `last_modified`; + +-- table: ActivityTemplate + +alter table `ActivityTemplate` rename column `dateCreated` to `date_created`; +alter table `ActivityTemplate` rename column `lastModified` to `last_modified`; + +-- table: file_description + +alter table `file_description` rename column `dateCreated` to `date_created`; +alter table `file_description` rename column `lastModified` to `last_modified`; + +-- table: answer + +alter table `answer` rename column `dateCreated` to `date_created`; +alter table `answer` rename column `lastModified` to `last_modified`; + +-- table: ApplicationPeriod + +alter table `ApplicationPeriod` rename column `dateCreated` to `date_created`; +alter table `ApplicationPeriod` rename column `lastModified` to `last_modified`; + +-- table: checklist + +alter table `checklist` rename column `dateCreated` to `date_created`; +alter table `checklist` rename column `lastModified` to `last_modified`; + +-- table: checklist_answer + +alter table `checklist_answer` rename column `dateCreated` to `date_created`; +alter table `checklist_answer` rename column `lastModified` to `last_modified`; + +-- table: checklist_category + +alter table `checklist_category` rename column `dateCreated` to `date_created`; +alter table `checklist_category` rename column `lastModified` to `last_modified`; + +-- table: checklist_question + +alter table `checklist_question` rename column `dateCreated` to `date_created`; +alter table `checklist_question` rename column `lastModified` to `last_modified`; + +-- table: checklist_template + +alter table `checklist_template` rename column `dateCreated` to `date_created`; +alter table `checklist_template` rename column `lastModified` to `last_modified`; + +-- table: comment + +alter table `comment` rename column `dateCreated` to `date_created`; +alter table `comment` rename column `lastModified` to `last_modified`; + +-- table: externallink + +alter table `externallink` rename column `dateCreated` to `date_created`; +alter table `externallink` rename column `lastModified` to `last_modified`; + +-- table: comment_thread + +alter table `comment_thread` rename column `dateCreated` to `date_created`; +alter table `comment_thread` rename column `lastModified` to `last_modified`; + +-- table: FinalSeminarSettings + +alter table `FinalSeminarSettings` rename column `dateCreated` to `date_created`; +alter table `FinalSeminarSettings` rename column `lastModified` to `last_modified`; + +-- table: FinalThesis + +alter table `FinalThesis` rename column `dateCreated` to `date_created`; +alter table `FinalThesis` rename column `lastModified` to `last_modified`; + +-- table: footer_address + +alter table `footer_address` rename column `dateCreated` to `date_created`; +alter table `footer_address` rename column `lastModified` to `last_modified`; + +-- table: footer_link + +alter table `footer_link` rename column `dateCreated` to `date_created`; +alter table `footer_link` rename column `lastModified` to `last_modified`; + +-- table: general_system_settings + +alter table `general_system_settings` rename column `dateCreated` to `date_created`; +alter table `general_system_settings` rename column `lastModified` to `last_modified`; + +-- table: grading_report_template + +alter table `grading_report_template` rename column `dateCreated` to `date_created`; +alter table `grading_report_template` rename column `lastModified` to `last_modified`; + +-- table: project_group + +alter table `project_group` rename column `dateCreated` to `date_created`; +alter table `project_group` rename column `lastModified` to `last_modified`; + +-- table: idea + +alter table `idea` rename column `dateCreated` to `date_created`; +alter table `idea` rename column `lastModified` to `last_modified`; + +-- table: idea_export + +alter table `idea_export` rename column `dateCreated` to `date_created`; +alter table `idea_export` rename column `lastModified` to `last_modified`; + +-- table: mail_event + +alter table `mail_event` rename column `dateCreated` to `date_created`; +alter table `mail_event` rename column `lastModified` to `last_modified`; + +-- table: idea_match + +alter table `idea_match` rename column `dateCreated` to `date_created`; +alter table `idea_match` rename column `lastModified` to `last_modified`; + +-- table: milestone + +alter table `milestone` rename column `dateCreated` to `date_created`; +alter table `milestone` rename column `lastModified` to `last_modified`; + +-- table: NonWorkDayPeriod + +alter table `NonWorkDayPeriod` rename column `dateCreated` to `date_created`; +alter table `NonWorkDayPeriod` rename column `lastModified` to `last_modified`; + +-- table: note + +alter table `note` rename column `dateCreated` to `date_created`; +alter table `note` rename column `lastModified` to `last_modified`; + +-- table: Notification + +alter table `Notification` rename column `dateCreated` to `date_created`; +alter table `Notification` rename column `lastModified` to `last_modified`; + +-- table: NotificationData + +alter table `NotificationData` rename column `dateCreated` to `date_created`; +alter table `NotificationData` rename column `lastModified` to `last_modified`; + +-- table: peer_request + +alter table `peer_request` rename column `dateCreated` to `date_created`; +alter table `peer_request` rename column `lastModified` to `last_modified`; + +-- table: peer_review + +alter table `peer_review` rename column `dateCreated` to `date_created`; +alter table `peer_review` rename column `lastModified` to `last_modified`; + +-- table: preliminary_match + +alter table `preliminary_match` rename column `dateCreated` to `date_created`; +alter table `preliminary_match` rename column `lastModified` to `last_modified`; + +-- table: Program + +alter table `Program` rename column `dateCreated` to `date_created`; +alter table `Program` rename column `lastModified` to `last_modified`; + +-- table: project + +alter table `project` rename column `dateCreated` to `date_created`; +alter table `project` rename column `lastModified` to `last_modified`; + +-- table: project_file + +alter table `project_file` rename column `dateCreated` to `date_created`; +alter table `project_file` rename column `lastModified` to `last_modified`; + +-- table: project_first_meeting + +alter table `project_first_meeting` rename column `dateCreated` to `date_created`; +alter table `project_first_meeting` rename column `lastModified` to `last_modified`; + +-- table: projectPartner + +alter table `projectPartner` rename column `dateCreated` to `date_created`; +alter table `projectPartner` rename column `lastModified` to `last_modified`; + +-- table: project_type_settings + +alter table `project_type_settings` rename column `dateCreated` to `date_created`; +alter table `project_type_settings` rename column `lastModified` to `last_modified`; + +-- table: reviewer_deadline_settings + +alter table `reviewer_deadline_settings` rename column `dateCreated` to `date_created`; +alter table `reviewer_deadline_settings` rename column `lastModified` to `last_modified`; + +-- table: reviewer_target + +alter table `reviewer_target` rename column `dateCreated` to `date_created`; +alter table `reviewer_target` rename column `lastModified` to `last_modified`; + +-- table: unit + +alter table `unit` rename column `dateCreated` to `date_created`; +alter table `unit` rename column `lastModified` to `last_modified`; + +-- table: urkund_submission + +alter table `urkund_submission` rename column `dateCreated` to `date_created`; +alter table `urkund_submission` rename column `lastModified` to `last_modified`; + +-- table: username + +alter table `username` rename column `dateCreated` to `date_created`; +alter table `username` rename column `lastModified` to `last_modified`; + +-- table: user_profile + +alter table `user_profile` rename column `dateCreated` to `date_created`; +alter table `user_profile` rename column `lastModified` to `last_modified`; + +-- table: worker_data + +alter table `worker_data` rename column `dateCreated` to `date_created`; +alter table `worker_data` rename column `lastModified` to `last_modified`; + +-- table: criterion + +alter table `criterion` rename column `dateCreated` to `date_created`; +alter table `criterion` rename column `lastModified` to `last_modified`; + +-- table: grading_criterion_template + +alter table `grading_criterion_template` rename column `dateCreated` to `date_created`; +alter table `grading_criterion_template` rename column `lastModified` to `last_modified`; + +-- table: GradingCriterion + +alter table `GradingCriterion` rename column `dateCreated` to `date_created`; +alter table `GradingCriterion` rename column `lastModified` to `last_modified`; + +-- table: GradingCriterionPoint + +alter table `GradingCriterionPoint` rename column `dateCreated` to `date_created`; +alter table `GradingCriterionPoint` rename column `lastModified` to `last_modified`; + +-- table: grading_criterion_point_template + +alter table `grading_criterion_point_template` rename column `dateCreated` to `date_created`; +alter table `grading_criterion_point_template` rename column `lastModified` to `last_modified`; + +-- table: ReviewerApproval + +alter table `ReviewerApproval` rename column `dateCreated` to `date_created`; +alter table `ReviewerApproval` rename column `lastModified` to `last_modified`; + +-- table: final_seminar_active_participation + +alter table `final_seminar_active_participation` rename column `dateCreated` to `date_created`; +alter table `final_seminar_active_participation` rename column `lastModified` to `last_modified`; + +-- table: final_seminar_opposition + +alter table `final_seminar_opposition` rename column `dateCreated` to `date_created`; +alter table `final_seminar_opposition` rename column `lastModified` to `last_modified`; + +-- table: final_seminar_respondent + +alter table `final_seminar_respondent` rename column `dateCreated` to `date_created`; +alter table `final_seminar_respondent` rename column `lastModified` to `last_modified`; + +-- table: report + +alter table `report` rename column `dateCreated` to `date_created`; +alter table `report` rename column `lastModified` to `last_modified`; + +-- table: notification_delivery_configuration + +alter table `notification_delivery_configuration` rename column `dateCreated` to `date_created`; +alter table `notification_delivery_configuration` rename column `lastModified` to `last_modified`; + +-- table: notification_receiver_configuration + +alter table `notification_receiver_configuration` rename column `dateCreated` to `date_created`; +alter table `notification_receiver_configuration` rename column `lastModified` to `last_modified`; + +-- table: Activity + +alter table `Activity` rename column `dateCreated` to `date_created`; +alter table `Activity` rename column `lastModified` to `last_modified`; + +-- table: final_seminar + +alter table `final_seminar` rename column `dateCreated` to `date_created`; +alter table `final_seminar` rename column `lastModified` to `last_modified`; + +-- table: forum_post + +alter table `forum_post` rename column `dateCreated` to `date_created`; +alter table `forum_post` rename column `lastModified` to `last_modified`; + +-- table: thread + +alter table `thread` rename column `dateCreated` to `date_created`; +alter table `thread` rename column `lastModified` to `last_modified`; + +-- table: Keyword + +alter table `Keyword` rename column `dateCreated` to `date_created`; +alter table `Keyword` rename column `lastModified` to `last_modified`; + +-- table: milestone_activity_template + +alter table `milestone_activity_template` rename column `dateCreated` to `date_created`; +alter table `milestone_activity_template` rename column `lastModified` to `last_modified`; + +-- table: milestone_phase_template + +alter table `milestone_phase_template` rename column `dateCreated` to `date_created`; +alter table `milestone_phase_template` rename column `lastModified` to `last_modified`; + +-- table: Password + +alter table `Password` rename column `dateCreated` to `date_created`; +alter table `Password` rename column `lastModified` to `last_modified`; + +-- table: ProjectType + +alter table `ProjectType` rename column `dateCreated` to `date_created`; +alter table `ProjectType` rename column `lastModified` to `last_modified`; + +-- table: researcharea + +alter table `researcharea` rename column `dateCreated` to `date_created`; +alter table `researcharea` rename column `lastModified` to `last_modified`; + +-- table: user + +alter table `user` rename column `dateCreated` to `date_created`; +alter table `user` rename column `lastModified` to `last_modified`; + +/* + * Step 3: standalone tables + */ + +-- table: worker_data + +alter table `worker_data` rename column `lastRun` to `last_run`; +alter table `worker_data` rename column `lastSuccessfulRun` to `last_successful_run`; + +-- table: footer_link + +alter table `footer_link` rename column `footerColumn` to `footer_column`; + +-- table: NonWorkDayPeriod + +alter table `NonWorkDayPeriod` rename column `endDate` to `end_date`; +alter table `NonWorkDayPeriod` rename column `startDate` to `start_date`; + +rename table `NonWorkDayPeriod` to `non_work_day_period`; + +-- table: reviewer_deadline_settings + +alter table `reviewer_deadline_settings` rename column `roughDraftApproval` to `rough_draft_approval`; +alter table `reviewer_deadline_settings` rename column `finalSeminarApproval` to `final_seminar_approval`; +alter table `reviewer_deadline_settings` rename column `finalGrading` to `final_grading`; + +-- table: final_seminar_settings + +alter table `FinalSeminarSettings` rename column `daysAheadToCreate` to `days_ahead_to_create`; +alter table `FinalSeminarSettings` rename column `daysAheadToRegisterParticipation` to `days_ahead_to_register_participation`; +alter table `FinalSeminarSettings` rename column `daysAheadToRegisterOpposition` to `days_ahead_to_register_opposition`; +alter table `FinalSeminarSettings` rename column `daysAheadToUploadThesis` to `days_ahead_to_upload_thesis`; +alter table `FinalSeminarSettings` rename column `thesisMustBePDF` to `thesis_must_be_pdf`; +alter table `FinalSeminarSettings` rename column `evaluationURL` to `evaluation_url`; +alter table `FinalSeminarSettings` rename column `oppositionPriorityDays` to `opposition_priority_days`; + +rename table `FinalSeminarSettings` to `final_seminar_settings`; + +/* + * Step 4: general_system_settings and three related tables. + */ + +-- table: general_system_settings_system_module + +alter table `general_system_settings_system_modules` drop foreign key `general_system_settings_system_modules_ibfk_1`; +alter table `general_system_settings_system_modules` drop key `GeneralSystemSettings_id`; +alter table `general_system_settings_system_modules` drop primary key; + +alter table `general_system_settings_system_modules` rename column `GeneralSystemSettings_id` to `general_system_settings_id`; +alter table `general_system_settings_system_modules` rename column `systemModules` to `system_module`; + +rename table `general_system_settings_system_modules` to `general_system_settings_system_module`; + +alter table `general_system_settings_system_module` add primary key (general_system_settings_id, system_module); + +alter table `general_system_settings_system_module` + add constraint fk_general_system_settings_system_module_id + foreign key (general_system_settings_id) references general_system_settings (id) + on delete cascade on update cascade; + +-- table: general_system_settings_supervisor_change_recipient + +alter table `general_system_settings_supervisor_change_recipients` drop foreign key `FK7DA712D52AC37675`; +alter table `general_system_settings_supervisor_change_recipients` drop key `FK7DA712D52AC37675`; + +alter table `general_system_settings_supervisor_change_recipients` rename column `GeneralSystemSettings_id` to `general_system_settings_id`; + +rename table `general_system_settings_supervisor_change_recipients` to `general_system_settings_supervisor_change_recipient`; + +alter table `general_system_settings_supervisor_change_recipient` add primary key (general_system_settings_id, mail); + +alter table `general_system_settings_supervisor_change_recipient` + add constraint fk_general_system_settings_supervisor_change_recipient_id + foreign key (general_system_settings_id) references general_system_settings (id) + on delete cascade on update cascade; + +-- table: general_system_settings_alarm_recipient + +alter table `general_system_settings_alarm_recipients` drop foreign key `FK3C9272B2AC37675`; +alter table `general_system_settings_alarm_recipients` drop key `FK3C9272B2AC37675`; + +alter table `general_system_settings_alarm_recipients` rename column `GeneralSystemSettings_id` to `general_system_settings_id`; + +rename table `general_system_settings_alarm_recipients` to `general_system_settings_alarm_recipient`; + +alter table `general_system_settings_alarm_recipient` add primary key (general_system_settings_id, mail); + +alter table `general_system_settings_alarm_recipient` + add constraint fk_general_system_settings_alarm_recipient_id + foreign key (general_system_settings_id) references general_system_settings (id) + on delete cascade on update cascade; + +-- table: general_system_settings + +alter table `general_system_settings` rename column `daisyProfileLinkBaseURL` to `daisy_profile_link_base_url`; +alter table `general_system_settings` rename column `daisySelectResearchAreaURL` to `daisy_select_research_area_url`; +alter table `general_system_settings` rename column `projectPartnerDaysToLive` to `project_partner_days_to_live`; +alter table `general_system_settings` rename column `mailNotifications` to `mail_notifications`; +alter table `general_system_settings` rename column `mailFromName` to `mail_from_name`; +alter table `general_system_settings` rename column `systemFromMail` to `system_from_mail`; +alter table `general_system_settings` rename column `smtpServer` to `smtp_server`; +alter table `general_system_settings` rename column `peerDisplayLatestReviews` to `peer_display_latest_reviews`; +alter table `general_system_settings` rename column `numberOfLatestReviewsDisplayed` to `number_of_latest_reviews_displayed`; +alter table `general_system_settings` rename column `publicReviewsActivated` to `public_reviews_activated`; +alter table `general_system_settings` rename column `peerDownloadEnabled` to `peer_download_enabled`; +alter table `general_system_settings` rename column `sciproURL` to `scipro_url`; +alter table `general_system_settings` rename column `showSingleSignOn` to `show_single_sign_on`; +alter table `general_system_settings` rename column `matchResponsibleMail` to `match_responsible_mail`; +alter table `general_system_settings` rename column `reviewerSupportMail` to `reviewer_support_mail`; +alter table `general_system_settings` rename column `thesisSupportMail` to `thesis_support_mail`; +alter table `general_system_settings` rename column `externalRoomBookingURL` to `external_room_booking_url`; +alter table `general_system_settings` rename column `externalGettingStartedWithIdeaURL` to `external_getting_started_with_idea_url`; +alter table `general_system_settings` rename column `externalGradingURL` to `external_grading_url`; +alter table `general_system_settings` rename column `finalSurveyAvailable` to `final_survey_available`; +alter table `general_system_settings` rename column `activeProjectIdeaSupportMail` to `active_project_idea_support_mail`; + +/* + * Step 5: table user and related tables. + * + * Table user is one of four fundamental tables (other three: project, file_reference, ProjectType). All four + * tables have many foreign keys referenced to them. + * + * Related tables of table user are the tables which have no relationship with other three fundamental tables. Their + * foreign key references end at table user. + */ + +-- table: Program and user_program + +alter table `user_program` drop foreign key `user_program_program_id`; +alter table `user_program` drop key `user_program_program_id`; + +alter table `user_program` drop foreign key `user_program_user_id`; + +rename table `Program` to `program`; + +alter table `program` rename column `externalId` to `external_id`; +alter table `program` rename column `name` to `name_sv`; +alter table `program` rename column `nameEn` to `name_en`; + +alter table `user_program` + add constraint fk_user_program_program_id + foreign key (program_id) references program (id) + on delete cascade on update cascade; + +alter table `user_program` + add constraint fk_user_program_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: note + +alter table `note` drop foreign key `note_ibfk_1`; +alter table `note` drop key `user_id`; + +alter table `note` + add constraint fk_note_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: comment and comment_thread + +alter table `comment` drop foreign key `FK38A5EE5FE44F4DBE`; +alter table `comment` drop foreign key `FK38A5EE5F45F802F5`; +alter table `comment` drop key `FK38A5EE5FE44F4DBE`; +alter table `comment` drop key `FK38A5EE5F45F802F5`; + +alter table `comment_thread` drop key `UK_s0ve8ppa3snl8i1wocqwiuwn2`; +alter table `comment_thread` drop key `commentableKey`; + +alter table comment_thread rename column `commentableId` to `commentable_id`; +alter table comment_thread rename column `commentableKey` to `commentable_key`; + +alter table `comment_thread` add constraint uk_comment_thread_id_key unique(commentable_id, commentable_key); + +alter table comment rename column `commentThread_id` to `comment_thread_id`; +alter table comment rename column `creator_id` to `creator_user_id`; + +alter table `comment` + add constraint fk_comment_creator_user_id + foreign key (creator_user_id) references user (id) + on delete cascade on update cascade; + +alter table `comment` + add constraint fk_comment_comment_thread_id + foreign key (comment_thread_id) references comment_thread (id) + on delete cascade on update cascade; + +-- table: reviewer_target + +alter table `reviewer_target` drop foreign key `FK_ReviewerTarget_ReviewerId`; +alter table `reviewer_target` drop key `UK_ReviewerTarget_ReviewerId_Year`; + +alter table `reviewer_target` rename column `reviewer_id` to `reviewer_user_id`; + +alter table `reviewer_target` add constraint uk_reviewer_target_reviewer_user_id_year unique(reviewer_user_id, year); + +alter table `reviewer_target` + add constraint fk_reviewer_target_reviewer_user_id + foreign key (reviewer_user_id) references user (id) + on delete cascade on update cascade; + +-- table: notification_delivery_configuration + +alter table `notification_delivery_configuration` drop foreign key `FK7B2EE5BF895349BF`; +alter table `notification_delivery_configuration` drop key `FK7B2EE5BF895349BF`; +alter table `notification_delivery_configuration` drop key `one_setting_per_user`; + +alter table `notification_delivery_configuration` add constraint uk_one_setting_per_user unique(type, event, method, user_id); + +alter table `notification_delivery_configuration` + add constraint fk_notification_delivery_configuration_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: username + +alter table `username` drop foreign key `FK_17moq4bksxe30ihucce3jovdc`; +alter table `username` drop key `FK_17moq4bksxe30ihucce3jovdc`; +alter table `username` drop key `username_must_be_unique`; + +alter table `username` add constraint uk_username unique(username); + +alter table `username` + add constraint fk_username_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: user_role + +alter table `user_role` drop foreign key `user_role_user_id`; + +alter table `user_role` + add constraint fk_user_role_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: user_languages + +alter table `user_languages` drop foreign key `user_languages_user_id`; +alter table `user_languages` drop key `user_languages_user_id`; + +rename table `user_languages` to `user_language`; + +alter table `user_language` + add constraint fk_user_language_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +/* + * table: user, unit and Password + */ + +alter table `user` drop foreign key `FK_hpmviec1b7vdg23xtxsalwxw8`; +alter table `user` drop key `FK_hpmviec1b7vdg23xtxsalwxw8`; + +alter table `user` drop foreign key `user_unit_id`; +alter table `user` drop key `user_unit_id`; + +alter table `user` drop key `identifier`; +alter table `user` drop key `deleted_index`; + +-- rename columns in table user + +alter table `user` rename column `emailAddress` to `email_address`; +alter table `user` rename column `firstName` to `first_name`; +alter table `user` rename column `lastName` to `last_name`; +alter table `user` rename column `fullName` to `full_name`; +alter table `user` rename column `degreeType` to `degree_type`; + +alter table `user` add constraint uk_user_identifier unique(identifier); +create index idx_user_deleted on user(deleted); + +-- table: unit + +alter table `unit` drop key `identifier`; + +alter table `unit` rename column `matchResponsible` to `match_responsible`; + +alter table `unit` add constraint uk_unit_identifier unique(identifier); + +-- add FK from user to unit + +alter table `user` + add constraint fk_user_unit_id + foreign key (unit_id) references unit (id) + on delete cascade on update cascade; + +-- table: Password + +alter table `Password` drop foreign key `FK_43erxladp39q03wrco68hi9iq`; +alter table `Password` drop key `FK_43erxladp39q03wrco68hi9iq`; +alter table `Password` drop key `FK4C641EBB895349BF`; +alter table `Password` drop key `deleted_index`; +alter table `Password` drop key `UK_43erxladp39q03wrco68hi9iq`; +alter table `Password` drop key `user_id`; + +rename table `Password` to `password`; + +alter table `password` add constraint uk_password_user_id unique(user_id); +create index idx_password_deleted on password(deleted); + +alter table `password` + add constraint fk_password_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- add FK from user till password + +alter table `user` + add constraint fk_user_password_id + foreign key (password_id) references password (id) + on delete cascade on update cascade; + +-- table: user_profile + +alter table `user_profile` drop foreign key `FK_user_profile_user`; +alter table `user_profile` drop key `FK487E2135895349BF`; +alter table `user_profile` drop key `UK_ebc21hy5j7scdvcjt0jy6xxrv`; +alter table `user_profile` drop key `user_id`; + +alter table `user_profile` rename column `otherInfo` to `other_info`; +alter table `user_profile` rename column `phoneNumber` to `phone_number`; +alter table `user_profile` rename column `skypeId` to `skype_id`; +alter table `user_profile` rename column `mailCompilation` to `mail_compilation`; +alter table `user_profile` drop column `threadedForum`; +alter table `user_profile` rename column `defaultSupervisorFilter` to `default_supervisor_filter`; +alter table `user_profile` rename column `selectedRole` to `selected_role`; + +alter table `user_profile` add constraint uk_user_profile_user_id unique(user_id); + +alter table `user_profile` + add constraint fk_user_profile_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: user_profile_default_project_status_filter + +alter table `UserProfile_defaultProjectStatusFilter` drop foreign key `FK_user_profile_project_status_user_profile`; +alter table `UserProfile_defaultProjectStatusFilter` drop key `FK_icub74l6htav89sx85ar4qcqg`; + +rename table `UserProfile_defaultProjectStatusFilter` to `user_profile_default_project_status_filter`; + +alter table `user_profile_default_project_status_filter` rename column `UserProfile_id` to `user_profile_id`; +alter table `user_profile_default_project_status_filter` rename column `defaultProjectStatusFilter` to `default_project_status_filter`; + +alter table `user_profile_default_project_status_filter` + add constraint fk_user_profile_default_project_status_filter_user_profile_id + foreign key (user_profile_id) references user_profile (id) + on delete cascade on update cascade; + +-- table: user_profile_default_project_team_member_roles_filter + +alter table `UserProfile_defaultProjectTeamMemberRolesFilter` drop foreign key `FK_user_profile_role_user_profile`; +alter table `UserProfile_defaultProjectTeamMemberRolesFilter` drop key `FK_ibub74l6htav89sx85ar4qcqg`; + +rename table `UserProfile_defaultProjectTeamMemberRolesFilter` to `user_profile_default_project_team_member_roles_filter`; + +alter table `user_profile_default_project_team_member_roles_filter` rename column `UserProfile_id` to `user_profile_id`; +alter table `user_profile_default_project_team_member_roles_filter` rename column `defaultProjectTeamMemberRolesFilter` to `default_project_team_member_roles_filter`; + +alter table `user_profile_default_project_team_member_roles_filter` + add constraint fk_up_dp_tm_roles_filter_user_profile_id + foreign key (user_profile_id) references user_profile (id) + on delete cascade on update cascade; + +/* + * Step 6: table ProjectType and related tables. + * + * Table ProjectType is one of four fundamental tables (other three: project, file_reference, user). All four + * tables have many foreign keys referenced to them. + * + * Table ProjectType has 12 foreign keys referenced to it, this part is the most complex part of this refactoring. + */ + +-- table: user_profile_ProjectType, except foreign key to coming table project_type + +alter table `user_profile_ProjectType` drop foreign key `FK_user_profile_project_type_user_profile`; +alter table `user_profile_ProjectType` drop foreign key `FK_76s8320kw3w7bxp6lw7pmawfh`; +alter table `user_profile_ProjectType` drop key `FK_2blea2vk0b5cvgxjo1fy4p2j0`; +alter table `user_profile_ProjectType` drop key `FK_76s8320kw3w7bxp6lw7pmawfh`; + +rename table `user_profile_ProjectType` to `user_profile_project_type`; + +alter table `user_profile_project_type` rename column `defaultProjectTypeFilter_id` to `project_type_id`; + +alter table `user_profile_project_type` + add constraint fk_user_profile_project_type_user_profile_id + foreign key (user_profile_id) references user_profile (id) + on delete cascade on update cascade; + +-- table: ExternalResource, except foreign key to coming table project_type + +alter table `ExternalResource` drop foreign key `ExternalResource_ProjectType_relevantFor`; +alter table `ExternalResource` drop key `ExternalResource_ProjectType_relevantFor`; + +rename table `ExternalResource` to `external_resource`; + +alter table `external_resource` rename column `relevantFor_id` to `project_type_id`; + +-- table: project_type_project_modules, except foreign key to coming table project_type + +alter table `project_type_project_modules` drop foreign key `FK_4attsf1e22qpveesgl6o9b7lg`; +alter table `project_type_project_modules` drop key `FK_4attsf1e22qpveesgl6o9b7lg`; +alter table `project_type_project_modules` drop primary key; + +rename table `project_type_project_modules` to `project_type_project_module`; + +alter table `project_type_project_module` rename column `ProjectType_id` to `project_type_id`; +alter table `project_type_project_module` rename column `projectModules` to `project_module`; + +alter table `project_type_project_module` add primary key (project_type_id, project_module); + +-- table: project_type_settings, except foreign key to coming table project_type + +alter table `project_type_settings` drop foreign key `FK_project_class_settings_projectType`; +alter table `project_type_settings` drop key `FK_oxqyb1t8jo7cq2fx8j9slvloa`; +alter table `project_type_settings` drop key `UK_project_class_settings_projectType`; + +alter table `project_type_settings` rename column `numDaysBetweenPeerReviewsOnSameProject` to `num_days_between_peer_reviews_on_same_project`; +alter table `project_type_settings` rename column `numDaysToSubmitPeerReview` to `num_days_to_submit_peer_review`; +alter table `project_type_settings` rename column `projectType_id` to `project_type_id`; +alter table `project_type_settings` rename column `numDaysBeforePeerGetsCancelled` to `num_days_before_peer_gets_cancelled`; +alter table `project_type_settings` rename column `minAuthors` to `min_authors`; +alter table `project_type_settings` rename column `maxAuthors` to `max_authors`; +alter table `project_type_settings` rename column `maxFinalSeminarActiveParticipation` to `max_final_seminar_active_participation`; +alter table `project_type_settings` rename column `maxOpponentsOnFinalSeminar` to `max_opponents_on_final_seminar`; +alter table `project_type_settings` rename column `minFinalSeminarActiveParticipation` to `min_final_seminar_active_participation`; +alter table `project_type_settings` rename column `minOpponentsOnFinalSeminar` to `min_opponents_on_final_seminar`; +alter table `project_type_settings` rename column `minimumOppositionsToBeGraded` to `min_oppositions_to_be_graded`; +alter table `project_type_settings` rename column `minimumActiveParticipationsToBeGraded` to `min_active_participations_to_be_graded`; + +alter table `project_type_settings` add constraint uk_project_type_settings_project_type_id unique(project_type_id); + +-- table: grading_report_template, except foreign key to coming table project_type + +alter table `grading_report_template` drop foreign key `FK_grading_report_template_projectType`; +alter table `grading_report_template` drop key `FK_qovbb9ql33oaxprfr01w7ss9u`; +alter table `grading_report_template` drop key `UK_only_one_template_per_date_and_type`; + +alter table `grading_report_template` change `projectType_id` `project_type_id` bigint(20) not null after `failing_grade`; + +alter table `grading_report_template` add constraint uk_grading_report_template_project_type_id_valid_from unique(project_type_id, valid_from); + +-- table: grading_report_template_grade_limits + +alter table `grading_report_template_grade_limits` drop foreign key `FK_grade_limit_grading_report_template `; +alter table `grading_report_template_grade_limits` drop key `UK_one_grade_per_template`; + +rename table `grading_report_template_grade_limits` to `grading_report_template_grade_limit`; + +alter table `grading_report_template_grade_limit` change `grading_report_template_id` `grading_report_template_id` bigint(20) default null after `lower_limit`; + +alter table `grading_report_template_grade_limit` add constraint uk_grt_gl_grading_report_template_id_grade unique (grading_report_template_id, grade); + +alter table `grading_report_template_grade_limit` + add constraint fk_grt_gl_grading_report_template_id + foreign key (grading_report_template_id) references grading_report_template (id) + on delete cascade on update cascade; + +/* >>> START: table grading_criterion_template, GradingCriterion and criterion share same JPA MappedSuperclass, must be handled together. */ + +-- table: criterion (partially, only rename three columns, since this table criterion shares same +-- JPA MappedSuperclass AbstractCriterion with grading_criterion_template, and GradingCriterion + +alter table `criterion` rename column `title` to `title_sv`; +alter table `criterion` rename column `titleEn` to `title_en`; +alter table `criterion` rename column `sortOrder` to `sort_order`; + +-- table: GradingCriterion (partially, only rename four columns, since this table GradingCriterion shares same +-- JPA MappedSuperclass AbstractCriterion and AbstractGradingCriterion with grading_criterion_template. + +alter table `GradingCriterion` rename column `title` to `title_sv`; +alter table `GradingCriterion` rename column `titleEn` to `title_en`; +alter table `GradingCriterion` rename column `sortOrder` to `sort_order`; +alter table `GradingCriterion` rename column `pointsRequiredToPass` to `points_required_to_pass`; + +-- table: grading_criterion_template + +alter table `grading_criterion_template` drop foreign key `FK_b37xw6uyfj98ff2tsn5t8x5q`; +alter table `grading_criterion_template` drop key `FK_b37xw6uyfj98ff2tsn5t8x5q`; + +alter table `grading_criterion_template` rename column `title` to `title_sv`; +alter table `grading_criterion_template` rename column `titleEn` to `title_en`; +alter table `grading_criterion_template` rename column `sortOrder` to `sort_order`; +alter table `grading_criterion_template` rename column `pointsRequiredToPass` to `points_required_to_pass`; +alter table `grading_criterion_template` rename column `gradingReportTemplate_id` to `grading_report_template_id`; + +alter table `grading_criterion_template` + add constraint fk_gct_grading_report_template_id + foreign key (grading_report_template_id) references grading_report_template (id) + on delete cascade on update cascade; + +/* >>> END: */ + +/* >>> START: table grading_criterion_point_template and GradingCriterionPoint share same JPA MappedSuperclass, must be handled together. */ + +-- table: GradingCriterionPoint (partially, only rename two columns since this table and grading_criterion_pint_template +-- shares same MappedSuperclass AbstractGradingCriterionPoint. + +alter table `GradingCriterionPoint` rename column `description` to `description_sv`; +alter table `GradingCriterionPoint` rename column `descriptionEn` to `description_en`; + +-- table: grading_criterion_point_template + +alter table `grading_criterion_point_template` drop foreign key `FK_gradingCriterionTemplate_id`; +alter table `grading_criterion_point_template` drop key `FK_gradingCriterionTemplate_id`; + +alter table `grading_criterion_point_template` rename column `description` to `description_sv`; +alter table `grading_criterion_point_template` rename column `descriptionEn` to `description_en`; +alter table `grading_criterion_point_template` rename column `gradingCriterionTemplate_id` to `grading_criterion_template_id`; + +alter table `grading_criterion_point_template` + add constraint fk_gc_pt_grading_criterion_template_id + foreign key (grading_criterion_template_id) references grading_criterion_template (id) + on delete cascade on update cascade; + +/* >>> END: */ + +-- table: checklist_template_ProjectType, except foreign key to coming table project_type + +alter table `checklist_template_ProjectType` drop foreign key `FK_checklist_template_projectType_id`; +alter table `checklist_template_ProjectType` drop foreign key `FK_checklist_template_degree_level_checklist_template_id`; +alter table `checklist_template_ProjectType` drop key `FK_checklist_template_projectType_id`; +alter table `checklist_template_ProjectType` drop primary key; + +rename table `checklist_template_ProjectType` to `checklist_template_project_type`; + +alter table `checklist_template_project_type` rename column `projectType_id` to `project_type_id`; + +alter table `checklist_template_project_type` add primary key (checklist_template_id, project_type_id); + +alter table `checklist_template_project_type` + add constraint fk_ct_pt_checklist_template_id + foreign key (checklist_template_id) references checklist_template (id) + on delete cascade on update cascade; + +-- table: milestone_activity_template_ProjectType, except foreign key to coming table project_type + +alter table `milestone_activity_template_ProjectType` drop foreign key `FKFB3FC75180E42A0F`; +alter table `milestone_activity_template_ProjectType` drop foreign key `FKFB3FC75157F6B071`; +alter table `milestone_activity_template_ProjectType` drop key `FKFB3FC75180E42A0F`; +alter table `milestone_activity_template_ProjectType` drop key `FKFB3FC75157F6B071`; +alter table `milestone_activity_template_ProjectType` drop primary key; + +rename table `milestone_activity_template_ProjectType` to `milestone_activity_template_project_type`; + +alter table `milestone_activity_template_project_type` rename column `projectTypes_id` to `project_type_id`; + +alter table `milestone_activity_template_project_type` add primary key (`milestone_activity_template_id`, `project_type_id`); + +alter table `milestone_activity_template_project_type` + add constraint fk_ma_tpt_milestone_activity_template_id + foreign key (milestone_activity_template_id) references milestone_activity_template (id) + on delete cascade on update cascade; + +-- table: idea, we only remove foreign key from idea to ProjectType and rename the column projectType_id here. +-- This table has many related tables and will be fixed later. + +alter table `idea` drop foreign key `FK_idea_projectType`; +alter table `idea` drop key `FK_idea_projectType`; + +alter table `idea` rename column `projectType_id` to `project_type_id`; + +-- table: project, we only remove foreign key from project to ProjectType and rename the column projectType_id here. +-- This table has many related tables and will be fixed later. + +alter table `project` drop foreign key `FK_project_projectType`; +alter table `project` drop key `FKED904B19B2B6081F`; + +alter table `project` rename column `projectType_id` to `project_type_id`; + +/* + * Table target, projectPartner and ApplicationPeriodProjectType has not only foreign key referencing table ProjectType, + * but also foreign key referencing table ApplicationPeriod. Table ApplicationPeriodProjectType references to + * ActivityPlanTemplate as well. + * + * Table ActivityTemplate, ActivityPlanTemplate, ApplicationPeriod using camel case naming convention, + * ApplicationPeriod has a related table, applicationperiodexemption, and they all need to + * fixed as well, before ProjectType can be fixed. A foreign key from table idea to ApplicationPeriod needs to be removed + * before table ApplicationPeriod can be fixed. + * + * Removal of foreign keys and renaming of columns and table name must be fixed in following order: + * + * 1. target, projectPartner, ApplicationPeriodProjectType + * 2. ActivityTemplate and ActivityPlanTemplate + * 3. ApplicationPeriod, applicationperiodexcemption, and idea as well + * + * Foreign keys will be then added in reverse order, it's like a stack pop. + */ + +-- >>> STACK PUSH: 1st table group: target, projectPartner, ApplicationPeriodProjectType + +-- table: target, except foreign key to coming table project_type, and application_period + +alter table `target` drop foreign key `target_user_id`; +alter table `target` drop foreign key `FKCB7E7191A520201Eb`; +alter table `target` drop foreign key `FKCB7E7191790761A4b`; +alter table `target` drop key `FKCB7E7191A520201E`; +alter table `target` drop key `FKCB7E7191790761A4`; +alter table `target` drop primary key; + +alter table `target` rename column `applicationPeriodId` to `application_period_id`; +alter table `target` rename column `projectTypeId` to `project_type_id`; + +alter table `target` add primary key (application_period_id, project_type_id, user_id); + +alter table `target` + add constraint fk_target_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: projectPartner, except foreign key to coming table project_type, and application_period + +alter table `projectPartner` drop foreign key `FK_project_partner_project_type`; +alter table `projectPartner` drop foreign key `FK_ProjectPartner_ApplicationPeriod_applicationPeriod`; +alter table `projectPartner` drop foreign key `FK1882B6F895349BF`; +alter table `projectPartner` drop key `FK_ProjectPartner_ApplicationPeriod_applicationPeriod`; +alter table `projectPartner` drop key `FK_project_partner_project_type`; +alter table `projectPartner` drop key `FK1882B6F895349BF`; + +rename table `projectPartner` to `project_partner`; + +alter table `project_partner` rename column `infotext` to `info_text`; +alter table `project_partner` rename column `projectType_id` to `project_type_id`; +alter table `project_partner` rename column `applicationPeriod_id` to `application_period_id`; + +alter table `project_partner` + add constraint fk_project_partner_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: ApplicationPeriodProjectType, except foreign key to coming table application_period, project_type and activity_plan_template. + +alter table `ApplicationPeriodProjectType` drop foreign key `FK_hqebt63rl2mhogp66dy5m7upo`; +alter table `ApplicationPeriodProjectType` drop foreign key `FK_546usee339qh4g5otguwka3hi`; +alter table `ApplicationPeriodProjectType` drop foreign key `FK_3ku67jvegs1xxh8ykk023i7sb`; +alter table `ApplicationPeriodProjectType` drop key `FK_3ku67jvegs1xxh8ykk023i7sb`; +alter table `ApplicationPeriodProjectType` drop key `FK_546usee339qh4g5otguwka3hi`; +alter table `ApplicationPeriodProjectType` drop key `FK_hqebt63rl2mhogp66dy5m7upo`; +alter table `ApplicationPeriodProjectType` drop primary key; + +rename table `ApplicationPeriodProjectType` to `application_period_project_type`; + +alter table `application_period_project_type` rename column `applicationPeriod_id` to `application_period_id`; +alter table `application_period_project_type` rename column `projectType_id` to `project_type_id`; +alter table `application_period_project_type` rename column `activityPlanTemplate_id` to `activity_plan_template_id`; + +alter table `application_period_project_type` add primary key (application_period_id, project_type_id); + +-- >>> STACK PUSH: 2nd table group: ActivityPlanTemplate and ActivityTemplate + +-- table: ActivityTemplate, except foreign key to coming table activity_plan_template + +alter table `ActivityTemplate` drop foreign key `FK_ca5bhq3i6p2g292fo5l4fqtf`; +alter table `ActivityTemplate` drop foreign key `FK_activity_template_checklist_template`; +alter table `ActivityTemplate` drop key `FKD4434665C5FC509F`; +alter table `ActivityTemplate` drop key `FK_ca5bhq3i6p2g292fo5l4fqtf`; +alter table `ActivityTemplate` drop key `FK_667ye6la0yb5obk64v21knimn`; + +rename table `ActivityTemplate` to `activity_template`; + +alter table `activity_template` rename column `numberInOrder` to `number_in_order`; +alter table `activity_template` rename column `activityPlanTemplate_id` to `activity_plan_template_id`; +alter table `activity_template` rename column `daysOffset` to `days_offset`; +alter table `activity_template` rename column `checkListTemplate_id` to `checklist_template_id`; + +alter table `activity_template` + add constraint fk_activity_template_checklist_template_id + foreign key (checklist_template_id) references checklist_template (id) + on delete set null on update cascade; + +-- table: ActivityPlanTemplate (at this stage, no any foreign key is referenced to ActivityPlanTemplate) + +alter table `ActivityPlanTemplate` drop foreign key `FK_rgwf80yvcy2msbb6g80bae10p`; +alter table `ActivityPlanTemplate` drop key `FK_rgwf80yvcy2msbb6g80bae10p`; +alter table `ActivityPlanTemplate` drop key `FKACCF6522E44F4DBE`; + +rename table `ActivityPlanTemplate` to `activity_plan_template`; + +alter table `activity_plan_template` rename column `isSysAdminTemplate` to `is_sys_admin_template`; +alter table `activity_plan_template` rename column `creator_id` to `creator_user_id`; + +alter table `activity_plan_template` + add constraint fk_activity_plan_template_creator_user_id + foreign key (creator_user_id) references user (id) + on delete cascade on update cascade; + +-- Add back all foreign key references to activity_plan_template + +-- add foreign key reference from activity_template to activity_plan_template +alter table `activity_template` + add constraint fk_activity_template_activity_plan_template_id + foreign key (activity_plan_template_id) references activity_plan_template (id) + on delete cascade on update cascade; + +-- add foreign key reference from application_period_project_type to activity_plan_template +alter table `application_period_project_type` + add constraint fk_ap_pt_activity_plan_template_id + foreign key (activity_plan_template_id) references activity_plan_template (id) + on delete cascade on update cascade; + +-- >>> STACK POP: 2nd table group (ActivityPlanTemplate and ActivityTemplate) is done!!! + +-- >>> STACK PUSH: 3rd table group: ApplicationPeriod, applicationperiodexemption, idea + +-- table: applicationperiodexeption, except foreign key reference to coming table application_period + +alter table `applicationperiodexemption` drop foreign key `fk_application_period_exemption_user`; +alter table `applicationperiodexemption` drop foreign key `fk_application_period_exemption_application_period`; +alter table `applicationperiodexemption` drop foreign key `FK_4p3he5fymtmdgbkl3xwrodq36`; +alter table `applicationperiodexemption` drop key `i_user_application_period`; +alter table `applicationperiodexemption` drop key `i_application_period`; +alter table `applicationperiodexemption` drop key `i_user`; +alter table `applicationperiodexemption` drop key `FK_4p3he5fymtmdgbkl3xwrodq36`; +alter table `applicationperiodexemption` drop primary key; + +rename table `applicationperiodexemption` to `application_period_exemption`; + +alter table `application_period_exemption` rename column `endDate` to `end_date`; +alter table `application_period_exemption` rename column `grantedBy_id` to `granted_by_id`; +alter table `application_period_exemption` rename column `grantedOn` to `granted_on`; +alter table `application_period_exemption` rename column `applicationPeriodId` to `application_period_id`; + +alter table `application_period_exemption` add primary key (`application_period_id`,`user_id`,`type`); + +alter table `application_period_exemption` + add constraint fk_ape_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +alter table `application_period_exemption` + add constraint fk_ape_granted_by_id + foreign key (granted_by_id) references user (id) + on delete cascade on update cascade; + +-- table: idea, we only remove foreign key from idea to ApplicationPeriod and rename the column applicationPeriod_id here. +-- This table has many related tables and will be fixed later. + +alter table `idea` drop foreign key `FK6E051897BEC322C1`; +alter table `idea` drop key `FK6E051897BEC322C1`; + +alter table `idea` rename column `applicationPeriod_id` to `application_period_id`; + +-- table: ApplicationPeriod (at this stage, no any foreign key is referenced to ApplicationPeriod) + +rename table `ApplicationPeriod` to `application_period`; + +alter table `application_period` rename column `endDate` to `end_date`; +alter table `application_period` rename column `startDate` to `start_date`; +alter table `application_period` rename column `courseStartDate` to `course_start_date`; +alter table `application_period` rename column `courseEndDate` to `course_end_date`; + +-- Add back all foreign key references to application_period, since table application_period is ready + +-- add back foreign key reference from ide to application_period +alter table `idea` + add constraint fk_idea_application_period_id + foreign key (application_period_id) references application_period (id) + on delete cascade on update cascade; + +-- add back foreign key reference from application_period_exemption to application_period +alter table `application_period_exemption` + add constraint fk_ape_application_period_id + foreign key (application_period_id) references application_period (id) + on delete cascade on update cascade; + +-- >>> STACK POP: 3rd table group: ApplicationPeriod, applicationperiodexemption, idea is done!!! + +-- add back foreign key reference from application_period_project_type to application_period +alter table `application_period_project_type` + add constraint fk_ap_pt_application_period_id + foreign key (application_period_id) references application_period (id) + on delete cascade on update cascade; + +-- add back foreign key reference from project_partner to application_period +alter table `project_partner` + add constraint fk_project_partner_application_period_id + foreign key (application_period_id) references application_period (id) + on delete cascade on update cascade; + +-- add back foreign key reference from target to application_period +alter table `target` + add constraint fk_target_application_period_id + foreign key (application_period_id) references application_period (id) + on delete cascade on update cascade; + +-- table: ProjectType (finally!! at this stage, no any foreign key is referenced to ProjectType) + +rename table `ProjectType` to `project_type`; + +alter table `project_type` rename column `degreeType` to `degree_type`; + +-- Add back all foreign key references to project_type + +-- add back foreign key reference from application_period_project_type to project_type +alter table `application_period_project_type` + add constraint fk_ap_pt_project_type_id + foreign key (project_type_id) references project_type (id) + on delete cascade on update cascade; + +-- add back foreign key reference from project_partner to project_type +alter table `project_partner` + add constraint fk_project_partner_project_type_id + foreign key (project_type_id) references project_type (id) + on delete cascade on update cascade; + +-- add back foreign key reference from target to project_type +alter table `target` + add constraint fk_target_project_type_id + foreign key (project_type_id) references project_type (id) + on delete cascade on update cascade; + +-- >>> STACK POP: 1st table group: target, projectPartner, ApplicationPeriodProjectType is done!!! + +-- add back foreign key reference from project to project_type +alter table `project` + add constraint fk_project_project_type_id + foreign key (project_type_id) references project_type (id) + on delete cascade on update cascade; + +-- add back foreign key reference from idea to project_type +alter table `idea` + add constraint fk_idea_project_type_id + foreign key (project_type_id) references project_type (id) + on delete cascade on update cascade; + +-- add back foreign key reference from milestone_activity_template_project_type to project_type +alter table `milestone_activity_template_project_type` + add constraint fk_ma_tpt_project_type_id + foreign key (project_type_id) references project_type (id) + on delete cascade on update cascade; + +-- add back foreign key reference from checklist_template_project_type to project_type +alter table `checklist_template_project_type` + add constraint fk_ct_pt_project_type_id + foreign key (project_type_id) references project_type (id) + on delete cascade on update cascade; + +-- add back foreign key reference from grading_report_template to project_type +alter table `grading_report_template` + add constraint fk_grading_report_template_project_type_id + foreign key (project_type_id) references project_type (id) + on delete cascade on update cascade; + +-- add back foreign key reference from project_type_settings to project_type +alter table `project_type_settings` + add constraint fk_project_type_settings_project_type_id + foreign key (project_type_id) references project_type (id) + on delete cascade on update cascade; + +-- add back foreign key reference from project_type_project_module to project_type +alter table `project_type_project_module` + add constraint fk_project_type_project_module_project_type_id + foreign key (project_type_id) references project_type (id) + on delete cascade on update cascade; + +-- add back foreign key reference from external_resource to project_type +alter table `external_resource` + add constraint fk_external_resource_project_type_id + foreign key (project_type_id) references project_type (id) + on delete cascade on update cascade; + +-- add back foreign key reference from user_profile_project_type to project_type. +alter table `user_profile_project_type` + add constraint fk_user_profile_project_type_project_type_id + foreign key (project_type_id) references project_type (id) + on delete cascade on update cascade; + +/* + * Step 7: checklist related tables + */ + +-- table: checklist_checklist_question + +alter table `checklist_checklist_question` drop foreign key `FKC77ED98C64F9D54`; +alter table `checklist_checklist_question` drop foreign key `FKC77ED981F327355`; +alter table `checklist_checklist_question` drop key `FKC77ED981F327355`; +alter table `checklist_checklist_question` drop key `FKC77ED98C64F9D54`; +alter table `checklist_checklist_question` drop key `UK_o5ndj9lydqv17attv7uf8wlr`; +alter table `checklist_checklist_question` drop key `questions_id`; +alter table `checklist_checklist_question` drop primary key; + +alter table `checklist_checklist_question` rename column `questions_id` to `checklist_question_id`; + +alter table `checklist_checklist_question` add primary key (checklist_id, checklist_question_id); + +alter table `checklist_checklist_question` add constraint uk_ccq_checklist_question_id unique(checklist_question_id); + +alter table `checklist_checklist_question` + add constraint fk_ccq_checklist_question_id + foreign key (checklist_question_id) references checklist_question (id) + on delete cascade on update cascade; + +alter table `checklist_checklist_question` + add constraint fk_ccq_checklist_id + foreign key (checklist_id) references checklist (id) + on delete cascade on update cascade; + +-- table: Checklist_userLastOpenDate + +alter table `Checklist_userLastOpenDate` drop foreign key `FKF7E07AB26D025A9`; +alter table `Checklist_userLastOpenDate` drop foreign key `FKF7E07AB21F327355`; +alter table `Checklist_userLastOpenDate` drop key `FKF7E07AB26D025A9`; +alter table `Checklist_userLastOpenDate` drop key `FKF7E07AB21F327355`; +alter table `Checklist_userLastOpenDate` drop primary key; + +rename table `Checklist_userLastOpenDate` to `checklist_user_last_open_date`; + +alter table `checklist_user_last_open_date` rename column `CheckList_id` to `checklist_id`; +alter table `checklist_user_last_open_date` rename column `userLastOpenDate` to `last_open_date`; +alter table `checklist_user_last_open_date` rename column `userLastOpenDate_KEY` to `user_id`; + +alter table `checklist_user_last_open_date` add primary key (checklist_id, user_id); + +alter table `checklist_user_last_open_date` + add constraint fk_cu_lod_checklist_id + foreign key (checklist_id) references checklist(id) + on delete cascade on update cascade; + +alter table `checklist_user_last_open_date` + add constraint fk_cu_lod_user_id + foreign key (user_id) references user(id) + on delete cascade on update cascade; + +-- table: checklist_checklist_category + +alter table `checklist_checklist_category` drop foreign key `FK54F86EB08725F1D`; +alter table `checklist_checklist_category` drop foreign key `FK54F86EB01F327355`; +alter table `checklist_checklist_category` drop key `FK54F86EB08725F1D`; +alter table `checklist_checklist_category` drop key `FK54F86EB01F327355`; + +alter table `checklist_checklist_category` rename column `categories_id` to `checklist_category_id`; + +alter table `checklist_checklist_category` + add constraint fk_cca_checklist_id + foreign key (checklist_id) references checklist (id) + on delete cascade on update cascade; + +alter table `checklist_checklist_category` + add constraint fk_cca_checklist_category_id + foreign key (checklist_category_id) references checklist_category (id) + on delete cascade on update cascade; + +-- table: checklist_category + +alter table `checklist_category` drop key `categoryName`; +alter table `checklist_category` rename column `categoryName` to `category_name`; + +alter table `checklist_category` add constraint uk_checklist_category_category_name unique(category_name); + +-- table: checklist + +alter table `checklist` drop foreign key `FK_checklist_project`; +alter table `checklist` drop key `I_checkList_activity`; + +alter table `checklist` + add constraint fk_checklist_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +-- table : checklist_question_checklist_answer + +alter table `checklist_question_checklist_answer` drop foreign key `FK86395A5787D18D44`; +alter table `checklist_question_checklist_answer` drop foreign key `FK86395A574BFBD702`; +alter table `checklist_question_checklist_answer` drop key `FK86395A574BFBD702`; +alter table `checklist_question_checklist_answer` drop key `UK_47is0po5b69467hxbgr4a2gph`; +alter table `checklist_question_checklist_answer` drop key `answers_id`; + +alter table `checklist_question_checklist_answer` rename column `answers_id` to `checklist_answer_id`; + +alter table `checklist_question_checklist_answer` add constraint uk_cq_ca_checklist_answer_id unique(checklist_answer_id); + +alter table `checklist_question_checklist_answer` + add constraint fk_cq_ca_checklist_answer_id + foreign key (checklist_answer_id) references checklist_answer (id) + on delete cascade on update cascade; + +alter table `checklist_question_checklist_answer` + add constraint fk_cq_ca_checklist_question_id + foreign key (checklist_question_id) references checklist_question (id) + on delete cascade on update cascade; + +-- table: checklist_answer + +alter table `checklist_answer` drop foreign key `FK49936477895349BF`; +alter table `checklist_answer` drop key `FK49936477895349BF`; + +alter table `checklist_answer` + add constraint fk_checklist_answer_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- update to NOT_APPLICABLE because of typo in code +update `checklist_answer` set answer = 'NOT_APPLICABLE' where answer = 'NOT_APLICABLE'; +update `answer` set answer = 'NOT_APPLICABLE' where answer = 'NOT_APLICABLE'; + +-- table: checklist_question + +alter table `checklist_question` rename column `questionNumber` to `question_number`; + +-- table: ChecklistTemplate_questions + +alter table `ChecklistTemplate_questions` drop foreign key `FK872F7C0E869F0235`; +alter table `ChecklistTemplate_questions` drop key `FK872F7C0E869F0235`; + +rename table `ChecklistTemplate_questions` to `checklist_template_question`; + +alter table `checklist_template_question` rename column `CheckListTemplate_id` to `checklist_template_id`; +alter table `checklist_template_question` rename column `questions` to `question`; + +alter table `checklist_template_question` + add constraint fk_ctq_checklist_template_id + foreign key (checklist_template_id) references checklist_template (id) + on delete cascade on update cascade; + +-- table: checklist_template_checklist_category + +alter table `checklist_template_checklist_category` drop foreign key `FK4E82F4438725F1D`; +alter table `checklist_template_checklist_category` drop foreign key `FK4E82F44372B51E82`; +alter table `checklist_template_checklist_category` drop key `FK4E82F4438725F1D`; +alter table `checklist_template_checklist_category` drop key `FK4E82F44372B51E82`; + +alter table `checklist_template_checklist_category` rename column `categories_id` to `checklist_category_id`; + +alter table `checklist_template_checklist_category` + add constraint fk_ct_cc_checklist_template_id + foreign key (checklist_template_id) references checklist_template (id) + on delete cascade on update cascade; + +alter table `checklist_template_checklist_category` + add constraint fk_ct_cc_checklist_category_id + foreign key (checklist_category_id) references checklist_category (id) + on delete cascade on update cascade; + +-- table: checklist_template + +alter table `checklist_template` drop foreign key `FK14DA6F3E44F4DBE`; +alter table `checklist_template` drop key `FK14DA6F3E44F4DBE`; + +alter table `checklist_template` rename column `creator_id` to `creator_user_id`; +alter table `checklist_template` rename column `templateNumber` to `template_number`; + +alter table `checklist_template` + add constraint fk_checklist_template_creator_user_id + foreign key (creator_user_id) references user (id) + on delete cascade on update cascade; + +/* + * Step 8: Survey related related tables + */ + +-- table: SurveyAnswer_multipleAnswers, except foreign key to coming table survey_answer + +alter table `SurveyAnswer_multipleAnswers` drop foreign key `FK_SA`; +alter table `SurveyAnswer_multipleAnswers` drop key `FK_SA`; + +rename table `SurveyAnswer_multipleAnswers` to `survey_answer_multiple_answers`; + +alter table `survey_answer_multiple_answers` rename column `SurveyAnswer_id` to `survey_answer_id`; +alter table `survey_answer_multiple_answers` rename column `multipleAnswers` to `multiple_answers`; + +-- table: SurveyAnswer, except foreign key to coming table survey and question + +alter table `SurveyAnswer` drop foreign key `FK_answer_question`; +alter table `SurveyAnswer` drop foreign key `FK_answer_survey`; +alter table `SurveyAnswer` drop key `FK_answer_question`; +alter table `SurveyAnswer` drop key `FK_answer_survey`; + +rename table `SurveyAnswer` to `survey_answer`; + +-- add back foreign key reference from survey_answer_multiple_answers to survey_answer + +alter table `survey_answer_multiple_answers` + add constraint fk_sama_survey_answer_id + foreign key (survey_answer_id) references survey_answer (id) + on delete cascade on update cascade; + +-- table: Question_choices, except foreign key to coming table question + +alter table `Question_choices` drop foreign key `FK_question_choices_question`; +alter table `Question_choices` drop key `FK_question_choices_question`; + +rename table `Question_choices` to `question_choices`; + +-- table: Question + +rename table `Question` to `question`; + +-- add back foreign key reference from question_choices to question + +alter table `question_choices` + add constraint fk_question_choices_question_id + foreign key (question_id) references question (id) + on delete cascade on update cascade; + +-- add back foreign key references from survey_answer to question + +alter table `survey_answer` + add constraint fk_survey_answer_question_id + foreign key (question_id) references question (id) + on delete cascade on update cascade; + +-- table: survey + +alter table `Survey` drop foreign key `FK_survey_project`; +alter table `Survey` drop key `FK_survey_project`; +alter table `Survey` drop foreign key `FK_survey_user`; +alter table `Survey` drop key `FK_survey_user`; + +rename table `Survey` to `survey`; + +alter table `survey` + add constraint fk_survey_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +alter table `survey` + add constraint fk_survey_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- add back foreign key references from survey_answer to survey + +alter table `survey_answer` + add constraint fk_survey_answer_survey_id + foreign key (survey_id) references survey (id) + on delete cascade on update cascade; + +/* + * Step 9: Keyword and Research Area related tables + */ + +-- table: Keyword_researcharea, except foreign keys to coming table keyword and research_area + +alter table `Keyword_researcharea` drop foreign key `FKF8C66F5E98ED461`; +alter table `Keyword_researcharea` drop key `FKF8C66F5E98ED461`; +alter table `Keyword_researcharea` drop foreign key `FKF8C66F5E6F20ECBC`; +alter table `Keyword_researcharea` drop key `FKF8C66F5E6F20ECBC`; + +rename table `Keyword_researcharea` to `keyword_research_area`; + +alter table `keyword_research_area` rename column `Keyword_id` to `keyword_id`; +alter table `keyword_research_area` rename column `researchAreas_id` to `research_area_id`; + +-- table: idea_Keyword + +alter table `idea_Keyword` drop foreign key `FK3707EE21AE316F00`; +alter table `idea_Keyword` drop key `FK3707EE21AE316F00`; +alter table `idea_Keyword` drop foreign key `FK3707EE21BD1521C1`; + +alter table `idea_Keyword` drop primary key; + +rename table `idea_Keyword` to `idea_keyword`; + +alter table `idea_keyword` rename column `keywords_id` to `keyword_id`; + +alter table `idea_keyword` add primary key (idea_id, keyword_id); + +alter table `idea_keyword` + add constraint fk_idea_keyword_idea_id + foreign key (idea_id) references idea (id) + on delete cascade on update cascade; + +-- table: keyword + +alter table `Keyword` drop key `deleted_index`; + +rename table `Keyword` to `keyword`; + +create index idx_keyword_deleted on keyword (deleted); + +-- add back foreign key reference from table idea_keyword to table keyword + +alter table `idea_keyword` + add constraint fk_idea_keyword_keyword_id + foreign key (keyword_id) references keyword (id) + on delete cascade on update cascade; + +-- add back foreign key reference from table keyword_research_area to table keyword + +alter table `keyword_research_area` + add constraint fk_kra_keyword_id + foreign key (keyword_id) references keyword (id) + on delete cascade on update cascade; + +-- table: user_research_area + +alter table `user_research_area` drop foreign key `user_research_area_user_id`; +alter table `user_research_area` drop foreign key `user_research_area_research_area_id`; +alter table `user_research_area` drop key `user_research_area_research_area_id`; + +alter table `user_research_area` + add constraint fk_ura_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- drop foreign key from idea to table researcharea before we can proceed with that table, +-- change foreign key column name as well + +alter table `idea` drop foreign key `FK6E0518974E257FBF`; +alter table `idea` drop key `FK6E0518974E257FBF`; + +alter table `idea` rename column `researchArea_id` to `research_area_id`; + +-- drop foreign key from project to table researcharea before we can proceed with that table, +-- change foreign key column name as well + +alter table `project` drop foreign key `FK_research_area_id`; +alter table `project` drop key `FK_research_area_id`; + +alter table `project` rename column `researchArea_id` to `research_area_id`; + +-- table: researcharea + +alter table `researcharea` drop key `deleted_index`; +alter table `researcharea` drop key `identifier`; + +rename table `researcharea` to `research_area`; + +create index idx_research_area_deleted on research_area (deleted); + +alter table `research_area` add constraint uk_research_area_identifier unique (identifier); + +-- add back foreign key reference from table project to table research_area + +alter table `project` + add constraint fk_project_research_area_id + foreign key (research_area_id) references research_area (id) + on delete cascade on update cascade; + +-- add back foreign key reference from table idea to table research_area + +alter table `idea` + add constraint fk_idea_research_area_id + foreign key (research_area_id) references research_area (id) + on delete cascade on update cascade; + +-- add back foreign key reference from table user_research_area to table research_area + +alter table `user_research_area` + add constraint fk_ura_research_area_id + foreign key (research_area_id) references research_area (id) + on delete cascade on update cascade; + +-- add back foreign key reference from table keyword_research_area to table research_area + +alter table `keyword_research_area` + add constraint fk_kra_research_area_id + foreign key (research_area_id) references research_area (id) + on delete cascade on update cascade; + +/* + * Step 10: idea related tables + */ + +-- table: idea + +alter table `idea` drop foreign key `FK6E051897B9431B73`; +alter table `idea` drop foreign key `FK6E051897C1813915`; +alter table `idea` drop foreign key `FK6E051897E44F4DBE`; + +alter table `idea` drop key `FK6E051897C1813915`; +alter table `idea` drop key `FK6E051897B9431B73`; +alter table `idea` drop key `FK6E051897E44F4DBE`; + +alter table `idea` drop key `UK_only_one_idea_per_project`; + +alter table `idea` change `published` `published` bit(1) not null default b'1' after `type`; +alter table `idea` change `cachedStatus` `cached_status` varchar(255) default null after `published`; +alter table `idea` change `inactive` `inactive` tinyint(1) not null default 0 after `cached_status`; + +alter table `idea` change `practicalHow` `practical_how` longtext default null after `inactive`; +alter table `idea` change `theoryHow` `theory_how` longtext default null after `practical_how`; +alter table `idea` change `literature` `literature` longtext default null after `why`; + +alter table `idea` change `background` `background` longtext default null after `literature`; +alter table `idea` change `problem` `problem` longtext default null after `background`; +alter table `idea` change `method` `method` longtext default null after `problem`; +alter table `idea` change `interests` `interests` longtext default null after `method`; + +alter table `idea` rename column `creator_id` to `creator_user_id`; +alter table `idea` rename column `match_id` to `latest_match_id`; + +alter table `idea` add constraint uk_idea_project_id unique(project_id); + +alter table `idea` + add constraint fk_idea_creator_user_id + foreign key (creator_user_id) references user (id) + on delete cascade on update cascade; + +alter table `idea` + add constraint fk_idea_latest_match_id + foreign key (latest_match_id) references idea_match (id) + on delete cascade on update cascade; + +alter table `idea` + add constraint fk_idea_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +-- table: idea_language + +alter table `idea_language` drop foreign key `FK_idea_language_idea`; +alter table `idea_language` drop key `FK_idea_language_idea`; + +alter table `idea_language` + add constraint fk_idea_language_idea_id + foreign key (idea_id) references idea (id) + on delete cascade on update cascade; + +-- table: idea_export + +alter table `idea_export` drop foreign key `FK68FA705CFCDADF61`; +alter table `idea_export` drop key `FK68FA705CFCDADF61`; + +alter table `idea_export` + add constraint fk_idea_export_idea_id + foreign key (idea_id) references idea (id) + on delete cascade on update cascade; + +-- table: idea_first_meeting + +alter table `idea_first_meeting` drop foreign key `FK9393AA04FCDADF61`; +alter table `idea_first_meeting` drop key `FK9393AA04FCDADF61`; + +alter table `idea_first_meeting` drop key `UK_k4m4tupnikallbq3cq3llvlmk`; +alter table `idea_first_meeting` drop key `idea_id`; + +alter table `idea_first_meeting` rename column `firstMeetingDate` to `first_meeting_date`; +alter table `idea_first_meeting` change `room` `room` longtext not null after `first_meeting_date`; + +alter table `idea_first_meeting` + add constraint fk_idea_first_meeting_idea_id + foreign key (idea_id) references idea (id) + on delete cascade on update cascade; + +alter table `idea_first_meeting` + add constraint uk_idea_first_meeting_idea_id unique(idea_id); + +-- table: idea_match + +alter table `idea_match` drop foreign key `FK87EA481DFCDADF61`; +alter table `idea_match` drop foreign key `FK87EA481DA89FFB7F`; +alter table `idea_match` drop foreign key `idea_match_supervisor_id`; + +alter table `idea_match` drop key `FK87EA481DFCDADF61`; +alter table `idea_match` drop key `FK87EA481DA89FFB7F`; +alter table `idea_match` drop key `idea_match_supervisor_id`; + +alter table `idea_match` rename column `changedBy_id` to `changed_by_user_id`; +alter table `idea_match` rename column `supervisor_id` to `supervisor_user_id`; + +alter table `idea_match` + add constraint fk_idea_match_idea_id + foreign key (idea_id) references idea (id) + on delete cascade on update cascade; + +alter table `idea_match` + add constraint fk_idea_match_changed_by_user_id + foreign key (changed_by_user_id) references user (id) + on delete cascade on update cascade; + +alter table `idea_match` + add constraint fk_idea_match_supervisor_user_id + foreign key (supervisor_user_id) references user (id) + on delete cascade on update cascade; + +-- table: preliminary_match + +alter table `preliminary_match` drop foreign key `FK_preliminary_match_supervisor`; +alter table `preliminary_match` drop foreign key `FK_preliminary_match_idea`; + +alter table `preliminary_match` drop key `FK_preliminary_match_supervisor`; +alter table `preliminary_match` drop key `FK_preliminary_match_idea`; + +alter table `preliminary_match` change `comment` `comment` mediumtext default null after `version`; +alter table `preliminary_match` rename column `supervisor_id` to `supervisor_user_id`; + +alter table `preliminary_match` + add constraint fk_preliminary_match_idea_id + foreign key (idea_id) references idea (id) + on delete cascade on update cascade; + +alter table `preliminary_match` + add constraint fk_preliminary_match_supervisor_user_id + foreign key (supervisor_user_id) references user (id) + on delete cascade on update cascade; + +-- table: idea_student + +alter table `idea_student` drop foreign key `idea_student_user_id`; +alter table `idea_student` drop foreign key `FK9458BA93FCDADF61`; + +alter table `idea_student` drop key `idea_student_user_id`; +alter table `idea_student` drop key `FK9458BA93FCDADF61`; +alter table `idea_student` drop key `FK_c5py593l4g261jdkuvwdmcmgj`; + +alter table `idea_student` rename column `dateCreated` to `date_created`; +alter table `idea_student` change `id` `id` bigint(20) not null auto_increment first; + +alter table `idea_student` + add constraint fk_idea_student_idea_id + foreign key (idea_id) references idea (id) + on delete cascade on update cascade; + +alter table `idea_student` + add constraint fk_idea_student_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +/* + * Step 11: activity related tables + * + * Some tables of this group of tables need to be renamed. Because of how foreign keys reference to each other + * between them, the order and behavior of how the tables will be fixed looks like stack again. + * + * 1. Remove references from activity_final_seminar, activity_thread, project_first_meeting to activity, + * the fix these three tables, but wait to later before foreign keys are added back to becoming activity table. + * 2. Remove reference from Activity to ActivtyPlan, and fix table Activity, without adding back foreign key to + * becoming activity_plan table. + * 3. Fix ActivityPlan table, rename it to activity_plan. + * 4. Add back foreign key reference from activity to activity_plan + * 5. Add back foreign key reference from activity_final_seminar, activity_thread, project_first_meeting to + * activity table. + */ + +-- table: activity_final_seminar, except foreign key to becoming table activity + +alter table `activity_final_seminar` drop foreign key `activity_final_seminar_ibfk_2`; +alter table `activity_final_seminar` drop foreign key `activity_final_seminar_ibfk_1`; + +alter table `activity_final_seminar` drop key `activity_id`; + +alter table `activity_final_seminar` + add constraint fk_afs_final_seminar_id + foreign key (final_seminar_id) references final_seminar (id) + on delete cascade on update cascade; + +-- table: activity_thread, except foreign key to becoming table activity + +alter table `activity_thread` drop foreign key `FK_activity_thread_project_thread`; +alter table `activity_thread` drop foreign key `FK_activity_thread_activity`; + +alter table `activity_thread` drop key `FK_activity_thread_project_thread`; + +alter table `activity_thread` + add constraint fk_activity_thread_project_thread_id + foreign key (project_thread_id) references project_thread (id) + on delete cascade on update cascade; + +-- table: project_first_meeting, except foreign key to becoming table activity + +alter table `project_first_meeting` drop foreign key `FK_project_first_meeting_activity`; + +alter table `project_first_meeting` drop key `FK_project_first_meeting_activity`; + +alter table `project_first_meeting` change `room` `room` longtext not null after `version`; + +alter table `project_first_meeting` change `activity_id` `activity_id` bigint(20) not null after `room`; + +-- table: activity + +alter table `Activity` drop foreign key `FK_Activity_file_upload`; +alter table `Activity` drop foreign key `FK_Activity_ActivityPlan`; +alter table `Activity` drop foreign key `FK_activity_checkList`; + +alter table `Activity` drop key `FK_Activity_file_upload`; +alter table `Activity` drop key `activityTemplate_id_index`; +alter table `Activity` drop key `deleted_index`; +alter table `Activity` drop key `UK_activity_checkList`; + +rename table `Activity` to `activity`; + +alter table `activity` change `title` `title` varchar(500) not null after `deleted`; +alter table `activity` change `action` `action` varchar(64) not null default 'none' after `description`; +alter table `activity` change `editable` `editable` bit(1) not null default b'1' after `action`; + +alter table `activity` rename column `activityTemplate_id` to `activity_plan_id`; +alter table `activity` rename column `file_upload_reference_id` to `upload_file_reference_id`; + +alter table `activity` add constraint uk_activity_checklist_id unique (checklist_id); +create index idx_activity_deleted on activity(deleted); + +alter table `activity` + add constraint `fk_activity_checklist_id` + foreign key (checklist_id) references checklist (id) + on delete cascade on update cascade ; + +alter table `activity` + add constraint `fk_activity_upload_file_reference_id` + foreign key (upload_file_reference_id) references file_reference (id) + on delete cascade on update cascade ; + +-- table: ActivityPlan + +alter table `ActivityPlan` drop foreign key `fk_ActivityPlan_project_B`; +alter table `ActivityPlan` drop key `project_id`; + +rename table `ActivityPlan` to `activity_plan`; + +alter table `activity_plan` change `version` `version` int(4) not null default 0 after `last_modified`; +alter table `activity_plan` change `startDate` `start_date` datetime default null after `version`; + +alter table `activity_plan` add constraint uk_activity_plan_project_id unique (project_id); + +alter table `activity_plan` + add constraint `fk_activity_plan_project_id` + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +-- add foreign key reference from activity to activity_plan + +alter table `activity` + add constraint fk_activity_activity_plan_id + foreign key (activity_plan_id) references activity_plan (id) + on delete cascade on update cascade; + +-- Add back all foreign key references to activity + +-- add foreign key reference from project_first_meeting to activity + +alter table `project_first_meeting` + add constraint fk_project_first_meeting_activity_id + foreign key (activity_id) references activity (id) + on delete cascade on update cascade; + +-- add foreign key reference from activity_thread to activity + +alter table `activity_thread` + add constraint fk_activity_thread_activity_id + foreign key (activity_id) references activity (id) + on delete cascade on update cascade; + +-- add foreign key reference from activity_final_seminar to activity + +alter table `activity_final_seminar` + add constraint fk_afs_activity_id + foreign key (activity_id) references activity (id) + on delete cascade on update cascade; + +/* + * Step 12: Peer Review related tables + */ + +-- table: peer_request + +alter table `peer_request` drop foreign key `FK_peer_request_checklist_template`; +alter table `peer_request` drop foreign key `FK_peer_request_file`; +alter table `peer_request` drop foreign key `FK_ppnisfed4ipbg17rts8vbuqt8`; +alter table `peer_request` drop foreign key `peer_request_reviewer_id`; + +alter table `peer_request` drop key `FK_peer_request_file`; +alter table `peer_request` drop key `FK_ppnisfed4ipbg17rts8vbuqt8`; +alter table `peer_request` drop key `peer_request_reviewer_id`; +alter table `peer_request` drop key `FK514488B2869F0235`; +alter table `peer_request` drop key `FK514488B2C1813915`; + +alter table `peer_request` change `version` `version` int(4) not null default 0 after `last_modified`; +alter table `peer_request` change `language` `language` varchar(255) not null after `status`; + +alter table `peer_request` rename column `checkListTemplate_id` to `checklist_template_id`; +alter table `peer_request` rename column `requester_id` to `requester_user_id`; + +alter table `peer_request` change `checklist_template_id` `checklist_template_id` bigint(20) default null after `language`; +alter table `peer_request` change `file_reference_id` `file_reference_id` bigint(20) not null after `checklist_template_id`; + +alter table `peer_request` + add constraint fk_peer_request_checklist_template_id + foreign key (checklist_template_id) references checklist_template (id) + on delete set null on update cascade; + +alter table `peer_request` + add constraint fk_peer_request_file_reference_id + foreign key (file_reference_id) references file_reference (id) + on delete cascade on update cascade; + +alter table `peer_request` + add constraint fk_peer_request_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +alter table `peer_request` + add constraint fk_peer_request_requester_user_id + foreign key (requester_user_id) references user (id) + on delete cascade on update cascade; + +-- table: peer_review + +alter table `peer_review` drop foreign key `peer_review_reviewer_id`; +alter table `peer_review` drop foreign key `FK_n5wj0qsev5cf8acm0xhfrqlpg`; +alter table `peer_review` drop foreign key `FK_9ke7armwg3tfnghmschgo011f`; +alter table `peer_review` drop foreign key `FK_peer_review_file`; + +alter table `peer_review` drop key `peer_review_reviewer_id`; +alter table `peer_review` drop key `FK_n5wj0qsev5cf8acm0xhfrqlpg`; +alter table `peer_review` drop key `FKB00C90D5C1813915`; +alter table `peer_review` drop key `FK_9ke7armwg3tfnghmschgo011f`; +alter table `peer_review` drop key `FKB00C90D5CEE8709B`; +alter table `peer_review` drop key `FK_peer_review_file`; + +alter table `peer_review` change `version` `version` int(4) not null default 0 after `last_modified`; +alter table `peer_review` change `status` `status` varchar(255) not null after `comment`; +alter table `peer_review` change `deadline` `deadline` datetime not null after `status`; + +alter table `peer_review` change `file_reference_id` `file_reference_id` bigint(20) default null after `deadline`; +alter table `peer_review` change `peerRequest_id` `peer_request_id` bigint(20) not null; +alter table `peer_review` change `reviewer_id` `reviewer_user_id` bigint(20) not null; + +alter table `peer_review` + add constraint fk_peer_review_file_reference_id + foreign key (file_reference_id) references file_reference (id) + on delete cascade on update cascade; + +alter table `peer_review` + add constraint fk_peer_review_peer_request_id + foreign key (peer_request_id) references peer_request (id) + on delete cascade on update cascade; + +alter table `peer_review` + add constraint fk_peer_review_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +alter table `peer_review` + add constraint fk_peer_review_reviewer_user_id + foreign key (reviewer_user_id) references user (id) + on delete cascade on update cascade; + +-- table: answer + +alter table `answer` drop foreign key `FK_64r70sbiishrkuj1vn87vo53k`; + +alter table `answer` drop key `FK_64r70sbiishrkuj1vn87vo53k`; +alter table `answer` drop key `FKABCA3FBE2C41A959`; + +alter table `answer` change `version` `version` int(4) not null default 0 after `last_modified`; +alter table `answer` change `question` `question` longtext not null after `version`; +alter table `answer` change `answer` `answer` varchar(255) not null after `question`; + +alter table `answer` rename column `peerReview_id` to `peer_review_id`; + +alter table `answer` + add constraint fk_answer_peer_review_id + foreign key (peer_review_id) references peer_review (id) + on delete cascade on update cascade; + +/* + * Step 13: Milestone related tables + */ + +-- table: milestone + +alter table `milestone` drop foreign key `FKC0841970667E5A5E`; +alter table `milestone` drop foreign key `FKC0841970C1813915`; +alter table `milestone` drop foreign key `milestone_user_id`; + +alter table `milestone` drop key `FKC0841970667E5A5E`; +alter table `milestone` drop key `FKC0841970C1813915`; +alter table `milestone` drop key `milestone_user_id`; + +alter table `milestone` rename column `activity_id` to `milestone_activity_template_id`; + +alter table `milestone` + add constraint fk_milestone_milestone_activity_template_id + foreign key (milestone_activity_template_id) references milestone_activity_template (id) + on delete cascade on update cascade; + +alter table `milestone` + add constraint fk_milestone_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +alter table `milestone` + add constraint fk_milestone_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: milestone_activity_template, except foreign key to becoming table event + +alter table `milestone_activity_template` drop foreign key `milestone_activity_template_ibfk_1`; +alter table `milestone_activity_template` drop foreign key `FK42DAA8FE233E1A72`; + +alter table `milestone_activity_template` drop key `milestone_activity_template_ibfk_1`; +alter table `milestone_activity_template` drop key `FK42DAA8FE233E1A72`; +alter table `milestone_activity_template` drop key `deleted_index`; +alter table `milestone_activity_template` drop key `code`; + +alter table `milestone_activity_template` change `description` `description` varchar(255) default null after `title`; +alter table `milestone_activity_template` change `sortOrder` `sort_order` int(11) default null; +alter table `milestone_activity_template` change `editableByStudents` `editable_by_students` bit(1) not null default b'0' after `sort_order`; + +alter table `milestone_activity_template` change `phase` `milestone_phase_template_id` bigint(20) not null; +alter table `milestone_activity_template` change `activatedBy` `activated_by_event_name` varchar(191) default null; + +alter table `milestone_activity_template` add constraint uk_milestone_activity_template_code unique(code); + +create index idx_milestone_activity_template_deleted on milestone_activity_template (deleted); + +alter table `milestone_activity_template` + add constraint fk_mat_milestone_phase_template_id + foreign key (milestone_phase_template_id) references milestone_phase_template (id) + on delete cascade on update cascade; + +-- table: event + +rename table `Event` to `event`; + +-- add foreign key reference from milestone_activity_template to event +alter table `milestone_activity_template` + add constraint fk_mat_activated_by_event_name + foreign key (activated_by_event_name) references event (name) + on delete cascade on update cascade; + +-- table: milestone_phase_template + +alter table `milestone_phase_template` drop key `deleted_index`; + +alter table `milestone_phase_template` change `description` `description` varchar(255) default null after `title`; + +alter table `milestone_phase_template` rename column `sortOrder` to `sort_order`; + +create index idx_milestone_phase_template_deleted on milestone_phase_template (deleted); + +/* + * Step 14: Final Seminar related tables + */ + +-- table: final_seminar + +alter table `final_seminar` drop foreign key `FK_rv1p7wl0dnj25saiarmk55yvr`; +alter table `final_seminar` drop foreign key `FK_final_seminar_document_reference`; + +alter table `final_seminar` drop key `FK_final_seminar_document_reference`; +alter table `final_seminar` drop key `FK_rv1p7wl0dnj25saiarmk55yvr`; +alter table `final_seminar` drop key `deleted_index`; +alter table `final_seminar` drop key `FK49900D28C1813915`; + +alter table `final_seminar` drop key `UK_rv1p7wl0dnj25saiarmk55yvr`; + +alter table `final_seminar` change `version` `version` int(4) not null default 0 after `last_modified`; +alter table `final_seminar` change `deleted` `deleted` tinyint(1) not null after `version`; + +alter table `final_seminar` change `startDate` `start_date` datetime not null after `deleted`; +alter table `final_seminar` change `room` `room` varchar(255) not null after start_date; +alter table `final_seminar` change `maxOpponents` `max_opponents` int(11) not null after `room`; +alter table `final_seminar` change `maxParticipants` `max_participants` int(11) not null after `max_opponents`; +alter table `final_seminar` change `presentationLanguage` `presentation_lang` varchar(255) not null after `max_participants`; +alter table `final_seminar` change `documentUploadDate` `document_upload_date` datetime default null after `presentation_lang`; +alter table `final_seminar` change `extra_info` `extra_info` text default null after `document_upload_date`; +alter table `final_seminar` change `creationReason` `creation_reason` mediumtext default null after `extra_info`; +alter table `final_seminar` change `manualParticipants` `manual_participants` tinyint(1) not null default 0 after `creation_reason`; +alter table `final_seminar` change `project_id` `project_id` bigint(20) not null after `document_reference_id`; + +alter table `final_seminar` rename column `document_reference_id` to `document_file_reference_id`; + +alter table `final_seminar` add constraint uk_final_seminar_project_id unique(project_id); + +create index idx_final_seminar_deleted on final_seminar (deleted); + +alter table `final_seminar` + add constraint fk_final_seminar_document_file_reference_id + foreign key (document_file_reference_id) references file_reference (id) + on delete cascade on update cascade; + +alter table `final_seminar` + add constraint fk_final_seminar_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +-- table: final_seminar_active_participation + +alter table `final_seminar_active_participation` drop foreign key `final_seminar_active_participation_user_id`; +alter table `final_seminar_active_participation` drop foreign key `FK_mk920fce29yhjgv33wr69fe8a`; +alter table `final_seminar_active_participation` drop foreign key `FK_3si3rx7tv6ke9oeiq0hts3lm0`; + +alter table `final_seminar_active_participation` drop key `FK35AB727FF583C69F`; +alter table `final_seminar_active_participation` drop key `FK35AB727FC1813915`; +alter table `final_seminar_active_participation` drop key `FK_mk920fce29yhjgv33wr69fe8a`; +alter table `final_seminar_active_participation` drop key `FK_3si3rx7tv6ke9oeiq0hts3lm0`; +alter table `final_seminar_active_participation` drop key `final_seminar_active_participation_user_id`; + +alter table `final_seminar_active_participation` change `version` `version` int(4) not null default 0 after `last_modified`; +alter table `final_seminar_active_participation` change `grade` `grade` varchar(20) default null after `version`; + +alter table `final_seminar_active_participation` rename column `finalSeminar_id` to `final_seminar_id`; + +alter table `final_seminar_active_participation` + add constraint fk_fsap_final_seminar_id + foreign key (final_seminar_id) references final_seminar (id) + on delete cascade on update cascade; + +alter table `final_seminar_active_participation` + add constraint fk_fsap_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +alter table `final_seminar_active_participation` + add constraint fk_fsap_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +-- table: final_seminar_opposition + +alter table `final_seminar_opposition` drop foreign key `FK_62i59u7j6x5ma0iydx9no6m4i`; +alter table `final_seminar_opposition` drop foreign key `FK_final_seminar_opposition_report`; +alter table `final_seminar_opposition` drop foreign key `FK_hilhyo3tgq89pm27i4pxjaua`; +alter table `final_seminar_opposition` drop foreign key `final_seminar_opposition_user_id`; + +alter table `final_seminar_opposition` drop key `FK8CD13581F583C69F`; +alter table `final_seminar_opposition` drop key `FK8CD13581C1813915`; +alter table `final_seminar_opposition` drop key `FK_62i59u7j6x5ma0iydx9no6m4i`; +alter table `final_seminar_opposition` drop key `FK_hilhyo3tgq89pm27i4pxjaua`; +alter table `final_seminar_opposition` drop key `final_seminar_opposition_user_id`; +alter table `final_seminar_opposition` drop key `FK_final_seminar_opposition_report`; + +alter table `final_seminar_opposition` change `version` `version` int(4) not null default 0 after `last_modified`; +alter table `final_seminar_opposition` change `finalSeminar_id` `final_seminar_id` bigint(20) not null after `feedback`; +alter table `final_seminar_opposition` change `opponent_report_reference_id` + `opponent_report_file_reference_id` bigint(20) default null after `final_seminar_id`; +alter table `final_seminar_opposition` change `project_id` `project_id` bigint(20) not null + after `opponent_report_file_reference_id`; + +alter table `final_seminar_opposition` + add constraint fk_fso_final_seminar_id + foreign key (final_seminar_id) references final_seminar (id) + on delete cascade on update cascade; + +alter table `final_seminar_opposition` + add constraint fk_fso_opponent_report_file_reference_id + foreign key (opponent_report_file_reference_id) references file_reference (id) + on delete cascade on update cascade; + +alter table `final_seminar_opposition` + add constraint fk_fso_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +alter table `final_seminar_opposition` + add constraint fk_fso_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: final_seminar_respondent + +alter table `final_seminar_respondent` drop foreign key `final_seminar_respondent_user_id`; +alter table `final_seminar_respondent` drop foreign key `FK_final_seminar_respondent_id`; + +alter table `final_seminar_respondent` drop key `FK_final_seminar_respondent_id`; +alter table `final_seminar_respondent` drop key `final_seminar_respondent_user_id`; + +alter table `final_seminar_respondent` change `version` `version` int(4) not null default 0 after `last_modified`; +alter table `final_seminar_respondent` change `grade` `grade` varchar(20) default null after `version`; +alter table `final_seminar_respondent` change `finalSeminar_id` `final_seminar_id` bigint(20) not null after `grade`; + +alter table `final_seminar_respondent` + add constraint fk_fsr_final_seminar_id + foreign key (final_seminar_id) references final_seminar (id) + on delete cascade on update cascade; + +alter table `final_seminar_respondent` + add constraint fk_fsr_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +/* + * Step 14: Report and Criterion related tables + */ + +-- table: report + +alter table `report` change `submitted` `submitted` tinyint(1) not null default 0 after `version`; + +-- table: opposition_report + +alter table `opposition_report` drop foreign key `opposition_report_ibfk_1`; +alter table `opposition_report` drop foreign key `FK_opposition_report_seminar_opposition`; +alter table `opposition_report` drop foreign key `FK_opposition_report_attachment`; + +alter table `opposition_report` drop key `FK_opposition_report_attachment`; +alter table `opposition_report` drop key `FK_opposition_report_seminar_opposition`; + +alter table `opposition_report` drop key `UK_one_report_per_opponent`; + +alter table `opposition_report` change `thesisSummary` `thesis_summary` longtext default null after `id`; + +alter table `opposition_report` change `attachment_reference_id` `attachment_file_reference_id` + bigint(20) default null after `thesis_summary`; + +alter table `opposition_report` change `finalSeminarOpposition_id` `final_seminar_opposition_id` + bigint(20) not null after `attachment_file_reference_id`; + +alter table `opposition_report` add constraint uk_or_final_seminar_opposition_id + unique(final_seminar_opposition_id); + +alter table `opposition_report` + add constraint fk_or_id + foreign key (id) references report (id) + on delete cascade on update cascade; + +alter table `opposition_report` + add constraint fk_or_attachment_file_reference_id + foreign key (attachment_file_reference_id) references file_reference (id) + on delete cascade on update cascade; + +alter table `opposition_report` + add constraint fk_or_final_seminar_opposition_id + foreign key (final_seminar_opposition_id) references final_seminar_opposition (id) + on delete cascade on update cascade; + +-- table: criterion + +alter table `criterion` drop foreign key `FK_criterion_report`; + +alter table `criterion` drop key `FK_criterion_report`; + +alter table `criterion` change `title_sv` `title_sv` varchar(255) not null after `version`; +alter table `criterion` change `title_en` `title_en` varchar(255) not null default '' after `title_sv`; +alter table `criterion` change `description` `description_sv` varchar(2000) default null after `title_en`; +alter table `criterion` change `descriptionEn` `description_en` varchar(2000) default null after `description_sv`; +alter table `criterion` change `feedback` `feedback` longtext default null after `description_en`; +alter table `criterion` change `report_id` `report_id` bigint(20) not null after `sort_order`; + +alter table `criterion` + add constraint fk_criterion_report_id + foreign key (report_id) references report (id) + on delete cascade on update cascade; + +-- table: GradingCriterionPoint, except foreign key to becoming table grading_criterion + +alter table `GradingCriterionPoint` drop foreign key `FK_GradingCriterion_id`; + +alter table `GradingCriterionPoint` drop key `FK_GradingCriterion_id`; + +alter table `GradingCriterionPoint` change `GradingCriterion_id` `grading_criterion_id` bigint(20) not null + after `description_en`; + +rename table `GradingCriterionPoint` to `grading_criterion_point`; + +-- table: GradingCriterion, except foreign key to becoming table grading_report + +alter table `GradingCriterion` drop foreign key `FK_k2ynx2lcpdl969alj5nt3f7xx`; + +alter table `GradingCriterion` drop key `FK_k2ynx2lcpdl969alj5nt3f7xx`; + +alter table `GradingCriterion` change `title_sv` `title_sv` varchar(255) not null after `version`; +alter table `GradingCriterion` change `title_en` `title_en` varchar(255) not null default '' after `title_sv`; +alter table `GradingCriterion` change `type` `type` varchar(64) not null after `title_en`; +alter table `GradingCriterion` change `points_required_to_pass` `points_required_to_pass` int(11) not null after `type`; +alter table `GradingCriterion` change `feedback` `feedback` longtext default null after `points`; +alter table `GradingCriterion` change `gradingReport_id` `grading_report_id` bigint(20) not null after `flag`; + +rename table `GradingCriterion` to `grading_criterion`; + +-- add foreign key reference from grading_criterion_point to grading_criterion + +alter table `grading_criterion_point` + add constraint fk_gcp_grading_criterion_id + foreign key (grading_criterion_id) references grading_criterion (id) + on delete cascade on update cascade; + +-- table: SupervisorGradingReport, except foreign key to becoming table grading_report + +alter table `SupervisorGradingReport` drop foreign key `supervisor_grading_report_user_id`; +alter table `SupervisorGradingReport` drop foreign key `FK_cwxdypciob8dmndx5elwi3fe5`; + +alter table `SupervisorGradingReport` drop key `supervisor_grading_report_user_id`; +alter table `SupervisorGradingReport` drop key `FK_cwxdypciob8dmndx5elwi3fe5`; + +rename table `SupervisorGradingReport` to `supervisor_grading_report`; + +alter table `supervisor_grading_report` + add constraint fk_sgr_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: ReviewerGradingReport, except foreign key to becoming table grading_report + +alter table `ReviewerGradingReport` drop foreign key `FK_axsaeqbamfc41dhih1s62g998`; + +alter table `ReviewerGradingReport` drop key `FK_axsaeqbamfc41dhih1s62g998`; + +rename table `ReviewerGradingReport` to `reviewer_grading_report`; + +-- table: GradingReport + +alter table `GradingReport` drop foreign key `GradingReport_ibfk_1`; +alter table `GradingReport` drop foreign key `FK_6ygpk1qq218jgwuuyx0bp6vui`; + +alter table `GradingReport` drop key `FK_6ygpk1qq218jgwuuyx0bp6vui`; + +rename table `GradingReport` to `grading_report`; + +alter table `grading_report` + add constraint fk_grading_report_id + foreign key (id) references report (id) + on delete cascade on update cascade; + +alter table `grading_report` + add constraint fk_grading_report_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +-- add foreign key reference from reviewer_grading_report to grading_report + +alter table `reviewer_grading_report` + add constraint fk_reviewer_grading_report_id + foreign key (id) references grading_report (id) + on delete cascade on update cascade; + +-- add foreign key reference from supervisor_grading_report to grading_report + +alter table `supervisor_grading_report` + add constraint fk_sgr_id + foreign key (id) references grading_report (id) + on delete cascade on update cascade; + +-- add foreign key reference from grading_criterion to grading_report + +alter table `grading_criterion` + add constraint fk_grading_criterion_grading_report_id + foreign key (grading_report_id) references grading_report (id) + on delete cascade on update cascade; + +/* + * Step 15: project and related tables + */ + +-- table: project + +alter table `project` drop foreign key `project_supervisor_id`; +alter table `project` drop key `project_supervisor_id`; +alter table `project` drop key `identifier`; + +alter table `project` change `version` `version` int(4) not null default 0 after `last_modified`; +alter table `project` change `title` `title` longtext not null after `version`; +alter table `project` change `credits` `credits` int(11) not null default 0 after `title`; +alter table `project` change `language` `language` varchar(255) default null after credits; +alter table `project` change `start_date` `start_date` date not null after language; +alter table `project` change `expected_end_date` `expected_end_date` date default null after `start_date`; +alter table `project` change `externalOrganization` `external_organization` varchar(255) default null after `expected_end_date`; +alter table `project` change `projectStatus` `project_status` varchar(255) default null after `external_organization`; +alter table `project` change `fs_rule_exmpt` `final_seminar_rule_exmpt` bit(1) not null default b'0' after `project_status`; +alter table `project` change `stateOfMind` `state_of_mind` varchar(255) default null after `final_seminar_rule_exmpt`; +alter table `project` change `stateOfMindReason` `state_of_mind_reason` varchar(255) default null after `state_of_mind`; +alter table `project` change `stateOfMindDate` `state_of_mind_date` datetime default null after `state_of_mind_reason`; +alter table `project` change `identifier` `daisy_identifier` bigint(20) default null after `state_of_mind_date`; +alter table `project` change `supervisor_id` `supervisor_id` bigint(20) not null after `research_area_id`; + +alter table `project` add constraint uk_project_daisy_identifier unique(daisy_identifier); + +alter table `project` + add constraint fk_project_supervisor_id + foreign key (supervisor_id) references user (id) + on delete cascade on update cascade; + +-- table: grading_history_rejections + +alter table `grading_history_rejections` drop foreign key `FK_grading_history_rejections_project`; + +alter table `grading_history_rejections` drop key `FK_grading_history_rejections_project`; + +alter table `grading_history_rejections` change `reason` `reason` text not null after `id`; +alter table `grading_history_rejections` change `when` `when` timestamp not null default '0000-00-00 00:00:00' after `reason`; + +rename table `grading_history_rejections` to `grading_history_rejection`; + +alter table `grading_history_rejection` + add constraint fk_grading_history_rejections_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +-- table: grading_history_approvals + +alter table `grading_history_approvals` drop foreign key `FK_grading_history_approvals_project`; + +alter table `grading_history_approvals` drop key `FK_grading_history_approvals_project`; + +alter table `grading_history_approvals` change `when` `when` timestamp not null default '0000-00-00 00:00:00' after `id`; + +rename table `grading_history_approvals` to `grading_history_approval`; + +alter table `grading_history_approval` + add constraint fk_grading_history_approval_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +-- table: national_subject_category + +alter table `national_subject_category` drop key `U_national_subject_category_external_id`; + +alter table `national_subject_category` change `swedish_name` `name_sv` varchar(255) not null after `id`; +alter table `national_subject_category` change `english_name` `name_en` varchar(255) not null after `name_sv`; +alter table `national_subject_category` change `external_id` `external_id` int(11) not null after `preselected`; + +alter table `national_subject_category` + add constraint uk_national_subject_category_external_id unique(external_id); + +-- table: publication_metadata + +alter table `publication_metadata` drop foreign key `FK_publication_metadata_project`; +alter table `publication_metadata` drop foreign key `FK_publication_metadata_national_subject_category`; + +alter table `publication_metadata` drop key `FK_publication_metadata_project`; +alter table `publication_metadata` drop key `FK_publication_metadata_national_subject_category`; + +alter table `publication_metadata` change `project_id` `project_id` bigint(20) not null after `national_subject_category_id`; + +alter table `publication_metadata` change `abstract_swedish` `abstract_sv` text default null after `id`; +alter table `publication_metadata` change `abstract_english` `abstract_en` text default null after `abstract_sv`; +alter table `publication_metadata` change `keywords_swedish` `keywords_sv` text default null after `abstract_en`; +alter table `publication_metadata` change `keywords_english` `keywords_en` text default null after `keywords_sv`; + +alter table `publication_metadata` + add constraint fk_publication_metadata_national_subject_category_id + foreign key (national_subject_category_id) references national_subject_category (id) + on delete cascade on update cascade; + +alter table `publication_metadata` + add constraint fk_publication_metadata_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +/* + * Step 16: Many-to-Many tables between project and user. + */ + +-- table: project_user_note (new changes from develop branch) + +alter table `project_user_note` drop foreign key `FK_project_user_note_user`; +alter table `project_user_note` drop foreign key `FK_project_user_note_project`; +alter table `project_user_note` drop key `FK_project_user_note_user`; + +alter table `project_user_note` + add constraint fk_project_user_note_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +alter table `project_user_note` + add constraint fk_project_user_note_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: project_cosupervisor + +alter table `project_cosupervisor` drop foreign key `FK_fj57t069dymdrnnhdxcnfvvnn`; +alter table `project_cosupervisor` drop foreign key `FK_18x2poxkt8s2bw9kpr7vbmd5j`; + +alter table `project_cosupervisor` drop key `FK_fj57t069dymdrnnhdxcnfvvnn`; +alter table `project_cosupervisor` drop key `FK_18x2poxkt8s2bw9kpr7vbmd5j`; + +alter table `project_cosupervisor` change `user_id` `user_id` bigint(20) not null after `project_id`; + +alter table `project_cosupervisor` + add constraint fk_project_cosupervisor_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +alter table `project_cosupervisor` + add constraint fk_project_cosupervisor_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: project_reviewer + +alter table `project_reviewer` drop foreign key `FK_g7yryw3e0dtmuuvgw5qjhphjm`; +alter table `project_reviewer` drop foreign key `FK_6aik0jd18kv3383fbt09xd0pi`; + +alter table `project_reviewer` drop key `FK_6aik0jd18kv3383fbt09xd0pi`; +alter table `project_reviewer` drop key `FK_g7yryw3e0dtmuuvgw5qjhphjm`; + +alter table `project_reviewer` + add constraint fk_project_reviewer_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +alter table `project_reviewer` + add constraint fk_project_reviewer_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: project_user + +alter table `project_user` drop foreign key `project_user_user_id`; +alter table `project_user` drop foreign key `project_user_project_id`; + +alter table `project_user` drop key `project_user_project_id`; + +alter table `project_user` change `user_id` `user_id` bigint(20) not null after `project_id`; +alter table `project_user` change `reflection` `reflection` text default null after `user_id`; + +alter table `project_user` + add constraint fk_project_user_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +alter table `project_user` + add constraint fk_project_user_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: grading_history_submissions + +alter table `grading_history_submissions` drop foreign key `FK_grading_history_submissions_project`; +alter table `grading_history_submissions` drop foreign key `FK_grading_history_submissions_author`; + +alter table `grading_history_submissions` drop key `FK_grading_history_submissions_project`; +alter table `grading_history_submissions` drop key `FK_grading_history_submissions_author`; + +rename table `grading_history_submissions` to `grading_history_submission`; + +alter table `grading_history_submission` change `when` `when` timestamp not null default '0000-00-00 00:00:00' after `id`; +alter table `grading_history_submission` change `corrections` `corrections` text default null after `when`; +alter table `grading_history_submission` change `author_id` `author_user_id` bigint(20) not null after `corrections`; + +alter table `grading_history_submission` + add constraint fk_grading_history_submission_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +alter table `grading_history_submission` + add constraint fk_grading_history_submission_author_user_id + foreign key (author_user_id) references user (id) + on delete cascade on update cascade; + +-- table: externallink + +alter table `externallink` drop foreign key `FK_PROJECT`; +alter table `externallink` drop foreign key `FK_USER`; + +alter table `externallink` drop key `FK_PROJECT`; +alter table `externallink` drop key `FK_USER`; + +rename table `externallink` to `external_link`; + +alter table `external_link` change `description` `description` varchar(255) default null after `url`; + +alter table `external_link` + add constraint fk_external_link_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +alter table `external_link` + add constraint fk_external_link_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: grade + +alter table `grade` drop foreign key `FK_grade_user_reportedBy`; +alter table `grade` drop foreign key `FK_grade_project`; + +alter table `grade` drop key `FK_grade_user_reportedBy`; +alter table `grade` drop key `project_id`; + +alter table `grade` change `value` `value` varchar(255) not null after `id`; +alter table `grade` change `reportedOn` `reported_when` date not null after `value`; +alter table `grade` change `project_id` `project_id` bigint(20) not null after `reported_when`; +alter table `grade` change `reportedBy` `reported_by_user_id` bigint(20) not null after `project_id`; + +alter table `grade` add constraint uk_grade_project_id unique(project_id); + +alter table `grade` + add constraint fk_grade_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +alter table `grade` + add constraint fk_grade_reported_by_user_id + foreign key (reported_by_user_id) references user (id) + on delete cascade on update cascade; + +/* + * Step 17: file_reference & file_description, FinalThesis and project_file + */ + +-- table: file_description + +alter table `file_description` drop foreign key `file_description_user`; + +alter table `file_description` drop key `file_description_user`; +alter table `file_description` drop key `file_description_identifier_index`; + +alter table `file_description` change `version` `version` int(4) not null default 0 after `last_modified`; +alter table `file_description` change `name` `name` varchar(255) default null after `version`; +alter table `file_description` change `mimeType` `mime_type` varchar(255) default null after `name`; +alter table `file_description` change `size` `size` bigint(20) default null after `mime_type`; +alter table `file_description` change `identifier` `file_identifier` varchar(255) default null after `size`; +alter table `file_description` change `type` `type` varchar(255) default null after `file_identifier`; +alter table `file_description` change `userId` `user_id` bigint(20) default null after `type`; + +alter table `file_description` + add constraint fk_file_description_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: file_reference + +alter table file_reference drop foreign key `FK_file_reference_file_description`; + +alter table file_reference drop key `FK_file_reference_file_description`; + +alter table file_reference + add constraint fk_file_reference_file_description_id + foreign key (file_description_id) references file_description (id) + on delete cascade on update cascade; + +-- table: FinalThesis + +alter table FinalThesis drop foreign key `FK_final_thesis_text_matching_document_reference`; +alter table FinalThesis drop foreign key `FK_final_thesis_project`; +alter table FinalThesis drop foreign key `FK_final_thesis_document_reference`; + +alter table FinalThesis drop key `FK_final_thesis_text_matching_document_reference`; +alter table FinalThesis drop key `FK_final_thesis_project`; + +rename table FinalThesis to `final_thesis`; + +alter table `final_thesis` change `swedishTitle` `title_sv` longtext default null after `version`; +alter table `final_thesis` change `englishTitle` `title_en` longtext default null after `title_sv`; +alter table `final_thesis` change `status` `status` varchar(32) not null after `title_en`; +alter table `final_thesis` change `dateApproved` `date_approved` date default null after `status`; +alter table `final_thesis` change `dateRejected` `date_rejected` date default null after `date_approved`; +alter table `final_thesis` change `rejection_comment` `rejection_comment` text default null after `date_rejected`; +alter table `final_thesis` change `text_matching_analysis` `text_matching_analysis` text default null after `rejection_comment`; +alter table `final_thesis` change `text_matching_document_reference_id` `text_matching_document_reference_id` bigint(20) default null after `text_matching_analysis`; +alter table `final_thesis` change `project_id` `project_id` bigint(20) not null after `document_reference_id`; + +alter table `final_thesis` + add constraint fk_final_thesis_text_matching_document_reference_id + foreign key (text_matching_document_reference_id) references file_reference (id) + on delete cascade on update cascade; + +alter table `final_thesis` + add constraint fk_final_thesis_document_reference_id + foreign key (document_reference_id) references file_reference (id) + on delete cascade on update cascade; + +alter table `final_thesis` + add constraint fk_final_thesis_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +-- table: project_file + +alter table `project_file` drop foreign key FK_project_file_project; +alter table `project_file` drop foreign key FK_project_file_file; + +alter table `project_file` drop key FK_project_file_file; +alter table `project_file` drop key FK_project_file_project; + +alter table `project_file` change `fileSource` `file_source` varchar(255) not null after `version`; +alter table `project_file` change `project_id` `project_id` bigint(20) not null after `file_reference_id`; + +alter table `project_file` + add constraint fk_project_file_file_reference_id + foreign key (file_reference_id) references file_reference (id) + on delete cascade on update cascade; + +alter table `project_file` + add constraint fk_project_file_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +/* + * Step 18: Decision & ReviewerApproval + */ + +-- table: Decision + +alter table `Decision` drop foreign key `fk_Decision_ReviewerApproval`; +alter table `Decision` drop foreign key `FK_decision_reviewer`; +alter table `Decision` drop foreign key `FK_Decision_thesis`; +alter table `Decision` drop foreign key `FK_Decision_attachment`; + +alter table `Decision` drop key `FK_decision_reviewer`; +alter table `Decision` drop key `FK_Decision_attachment`; +alter table `Decision` drop key `FK_Decision_thesis`; +alter table `Decision` drop key `fk_ReviewerApproval_Decision_idx`; + +rename table `Decision` to `decision`; + +alter table `decision` change `status` `status` varchar(255) default null after `id`; +alter table `decision` change `requested` `requested_date` datetime not null; +alter table `decision` change `decisionDate` `decision_date` datetime default null; +alter table `decision` change `deadline` `deadline` datetime default null after `decision_date`; +alter table `decision` change `assigned_reviewer_date` `assigned_reviewer_date` date default null after `deadline`; +alter table `decision` change `assigned_reviewer_id` `assigned_reviewer_id` bigint(20) default null after `assigned_reviewer_date`; +alter table `decision` change `attachment_reference_id` `attachment_reference_id` bigint(20) default null after `assigned_reviewer_id`; +alter table `decision` change `reviewerApproval_id` `reviewer_approval_id` bigint(20) not null; + +alter table `decision` + add constraint fk_decision_assigned_reviewer_id + foreign key (assigned_reviewer_id) references user (id) + on delete cascade on update cascade; + +alter table `decision` + add constraint fk_decision_attachment_reference_id + foreign key (attachment_reference_id) references file_reference (id) + on delete cascade on update cascade; + +alter table `decision` + add constraint fk_decision_thesis_reference_id + foreign key (thesis_reference_id) references file_reference (id) + on delete cascade on update cascade; + +-- table: ReviewerApproval + +alter table `ReviewerApproval` drop foreign key `FK_9lr1dn8boyfc5a0477ld4q8rw`; + +alter table `ReviewerApproval` drop key `FK_9lr1dn8boyfc5a0477ld4q8rw`; + +rename table `ReviewerApproval` to `reviewer_approval`; + +alter table `reviewer_approval` change `type` `type` varchar(64) not null after `version`; +alter table `reviewer_approval` change `project_id` `project_id` bigint(20) not null after `type`; + +alter table `reviewer_approval` + add constraint fk_reviewer_approval_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +-- add foreign key from decision to reviewer_approval + +alter table `decision` + add constraint fk_decision_reviewer_approval_id + foreign key (reviewer_approval_id) references reviewer_approval (id) + on delete cascade on update cascade; + +/* + * Step 19: urkund_submission & plagiarium_request + */ + +-- table: urkund_submission + +alter table `urkund_submission` drop foreign key `FK_urkund_submission_receiver`; +alter table `urkund_submission` drop foreign key `FK_urkund_submission_document_reference`; + +alter table `urkund_submission` drop key `FK_urkund_submission_document_reference`; +alter table `urkund_submission` drop key `FK_urkund_submission_receiver`; + +alter table `urkund_submission` change `document_reference_id` `document_file_reference_id` bigint(20) not null; +alter table `urkund_submission` change `receiver_id` `receiver_user_id` bigint(20) not null after `document_file_reference_id`; +alter table `urkund_submission` change `submitted` `submitted_date` datetime not null; +alter table `urkund_submission` change `nextPoll` `next_poll_date` datetime not null; +alter table `urkund_submission` change `pollingDelay` `polling_delay` varchar(16) not null; +alter table `urkund_submission` change `reportUrl` `report_url` varchar(255) default null; +alter table `urkund_submission` change `analysisAddress` `analysis_address` varchar(255) default null; + +alter table `urkund_submission` + add constraint fk_urkund_submission_document_file_reference_id + foreign key (document_file_reference_id) references file_reference (id) + on delete cascade on update cascade; + +alter table `urkund_submission` + add constraint fk_urkund_submission_receiver_user_id + foreign key (receiver_user_id) references user (id) + on delete cascade on update cascade; + +-- table: plagiarism_request + +alter table `plagiarism_request` drop foreign key `FK_plagiarism_request_receiver`; +alter table `plagiarism_request` drop foreign key `FK_plagiarism_request_document_reference`; + +alter table `plagiarism_request` drop key `FK_plagiarism_request_document_reference`; +alter table `plagiarism_request` drop key `FK_plagiarism_request_receiver`; + +alter table `plagiarism_request` change `document_reference_id` `document_file_reference_id` bigint(20) not null; +alter table `plagiarism_request` change `receiver_id` `receiver_user_id` bigint(20) not null after `document_file_reference_id`; + +alter table `plagiarism_request` + add constraint fk_plagiarism_request_document_file_reference_id + foreign key (document_file_reference_id) references file_reference (id) + on delete cascade on update cascade; + +alter table `plagiarism_request` + add constraint fk_plagiarism_request_receiver_user_id + foreign key (receiver_user_id) references user (id) + on delete cascade on update cascade; + +/* + * Step 20: mail_event, mail_event_recipients and MailEvent_nonUserRecipients + */ + +-- table: mail_event + +alter table `mail_event` drop foreign key `FK_mail_event_attachment`; + +alter table `mail_event` drop key `FK_mail_event_attachment`; + +alter table `mail_event` change `version` `version` int(4) not null default 0 after `last_modified`; +alter table `mail_event` change `subject` `subject` varchar(255) not null after `version`; +alter table `mail_event` change `fromName` `from_name` varchar(255) default null after `subject`; +alter table `mail_event` change `fromEmail` `from_email` varchar(255) default null after `from_name`; +alter table `mail_event` change `messageBody` `message_body` longtext not null after `from_email`; +alter table `mail_event` change `sent` `sent` tinyint(1) not null default 0 after `message_body`; +alter table `mail_event` change `messageID` `message_id` varchar(255) default null after `sent`; +alter table `mail_event` change `notificationEventType` `notification_event_type` varchar(255) default null after `message_id`; +alter table `mail_event` change `attachment_reference_id` `attachment_file_reference_id` bigint(20) default null after `notification_event_type`; + +alter table `mail_event` + add constraint fk_mail_event_attachment_file_reference_id + foreign key (attachment_file_reference_id) references file_reference (id) + on delete cascade on update cascade; + +-- table: mail_event_recipients + +alter table `mail_event_recipients` drop foreign key `FK_mail_event_recipients_user`; +alter table `mail_event_recipients` drop foreign key `FK41091C7FE7F98C6`; + +alter table `mail_event_recipients` drop key `FK41091C7B286D1B0`; +alter table `mail_event_recipients` drop key `FK41091C7FE7F98C6`; + +alter table `mail_event_recipients` drop primary key; + +rename table `mail_event_recipients` to `mail_event_recipient`; + +alter table `mail_event_recipient` change `recipients_id` `recipient_id` bigint(20) not null after `mail_event_id`; + +alter table `mail_event_recipient` add primary key (mail_event_id, recipient_id); + +alter table `mail_event_recipient` + add constraint fk_mail_event_recipient_mail_event_id + foreign key (mail_event_id) references mail_event (id) + on delete cascade on update cascade; + +alter table `mail_event_recipient` + add constraint fk_mail_event_recipient_recipient_id + foreign key (recipient_id) references user (id) + on delete cascade on update cascade; + +-- table: MailEvent_nonUserRecipients + +alter table `MailEvent_nonUserRecipients` drop foreign key `FKD7F8996D0814DF5`; +alter table `MailEvent_nonUserRecipients` drop key `FKD7F8996D0814DF5`; + +rename table `MailEvent_nonUserRecipients` to `mail_event_non_user_recipient`; + +alter table `mail_event_non_user_recipient` change `MailEvent_id` `mail_event_id` bigint(20) not null; +alter table `mail_event_non_user_recipient` change `nonUserRecipients` `non_user_recipient` varchar(255) default null; + +alter table `mail_event_non_user_recipient` + add constraint fk_mail_event_non_user_recipient_mail_event_id + foreign key (mail_event_id) references mail_event (id) + on delete cascade on update cascade; + +/* + * Step 21: project_group and project_group_project + */ + +-- table: project_group + +alter table `project_group` drop foreign key `FK_user_id`; +alter table `project_group` drop key `FK_user_id`; + +alter table `project_group` change `active` `active` bit(1) not null after `description`; + +alter table `project_group` + add constraint fk_project_group_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: project_group_project + +alter table `project_group_project` drop foreign key `FK_project_id`; +alter table `project_group_project` drop foreign key `FK_project_group_id`; + +alter table `project_group_project` drop key `FK_project_id`; +alter table `project_group_project` drop key `FK_project_group_id`; + +alter table `project_group_project` + add constraint fk_project_group_project_project_group_id + foreign key (project_group_id) references project_group (id) + on delete cascade on update cascade; + +alter table `project_group_project` + add constraint fk_project_group_project_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +/* + * Step 22: thread, forum_post and forum_post_file_description + */ + +-- table: thread + +alter table `thread` change `deleted` `deleted` tinyint(1) not null after `subject`; + +-- table: forum_post + +alter table `forum_post` drop foreign key `forum_posts_thread`; +alter table `forum_post` drop foreign key `FKEDDC4F35924F477B`; + +alter table `forum_post` drop key `deleted_index`; +alter table `forum_post` drop key `FKEDDC4F355E9380A1`; +alter table `forum_post` drop key `FKEDDC4F35924F477B`; + +alter table `forum_post` change `content` `content` longtext not null after `version`; +alter table `forum_post` change `thread` `thread_id` bigint(20) not null after `deleted`; +alter table `forum_post` change `user` `user_id` bigint(20) default null after `thread_id`; + +create index idx_forum_post_deleted on forum_post (deleted); + +alter table `forum_post` + add constraint fk_forum_post_thread_id + foreign key (thread_id) references thread (id) + on delete cascade on update cascade; + +alter table `forum_post` + add constraint fk_forum_post_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: forum_post_file_description + +alter table `forum_post_file_description` drop foreign key `FK_forum_post_file`; + +alter table `forum_post_file_description` drop key `I_forum_post_file_post`; +alter table `forum_post_file_description` drop key `FK_forum_post_file`; + +rename table `forum_post_file_description` to `forum_post_file_reference`; + +alter table `forum_post_file_reference` + add constraint fk_forum_post_file_reference_forum_post_id + foreign key (forum_post_id) references forum_post (id) + on delete cascade on update cascade; + +alter table `forum_post_file_reference` + add constraint fk_forum_post_file_reference_file_reference_id + foreign key (file_reference_id) references file_reference (id) + on delete cascade on update cascade; + +/* + * Step 23: forum_post_read, project_thread, reviewer_thread and group_thread + */ + +-- table: forum_post_read + +alter table `forum_post_read` drop foreign key `FK8A5DFC60DD74550D`; +alter table `forum_post_read` drop foreign key `FK8A5DFC60924F477B`; + +alter table `forum_post_read` drop key `FK8A5DFC60DD74550D`; +alter table `forum_post_read` drop key `FK8A5DFC60924F477B`; + +alter table `forum_post_read` drop primary key; + +rename table `forum_post_read` to `forum_post_read_state`; + +alter table `forum_post_read_state` change `read` `read` tinyint(1) not null after `post`; +alter table `forum_post_read_state` change `user` `user_id` bigint(20) not null after `post`; +alter table `forum_post_read_state` change `post` `forum_post_id` bigint(20) not null; + +alter table `forum_post_read_state` add primary key (forum_post_id, user_id); + +alter table `forum_post_read_state` + add constraint fk_forum_post_read_state_forum_post_id + foreign key (forum_post_id) references forum_post (id) + on delete cascade on update cascade; + +alter table `forum_post_read_state` + add constraint fk_forum_post_read_state_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: project_thread + +alter table `project_thread` drop foreign key `FK_project_thread_thread`; +alter table `project_thread` drop foreign key `FK_project_thread_project`; + +alter table `project_thread` drop key `FK_project_thread_thread`; +alter table `project_thread` drop key `FK_project_thread_project`; + +alter table `project_thread` change `project_id` `project_id` bigint(20) not null after `id`; + +alter table `project_thread` + add constraint fk_project_thread_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +alter table `project_thread` + add constraint fk_project_thread_thread_id + foreign key (thread_id) references thread (id) + on delete cascade on update cascade; + +-- table: reviewer_thread + +alter table `reviewer_thread` drop foreign key `FK_reviewer_thread_thread`; +alter table `reviewer_thread` drop foreign key `FK_reviewer_thread_group`; + +alter table `reviewer_thread` drop key `FK_reviewer_thread_thread`; +alter table `reviewer_thread` drop key `project_id`; + +alter table `reviewer_thread` change `thread_id` `thread_id` bigint(20) not null after `project_id`; + +alter table `reviewer_thread` add constraint uk_reviewer_thread_project_id unique(project_id, thread_id); + +alter table `reviewer_thread` + add constraint fk_reviewer_thread_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +alter table `reviewer_thread` + add constraint fk_reviewer_thread_thread_id + foreign key (thread_id) references thread (id) + on delete cascade on update cascade; + +-- table: group_thread + +alter table `group_thread` drop foreign key `FK_project_group_thread_thread`; +alter table `group_thread` drop foreign key `FK_project_group_thread_group`; + +alter table `group_thread` drop key `FK_project_group_thread_thread`; +alter table `group_thread` drop key `project_group`; + +rename table `group_thread` to `project_group_thread`; + +alter table `project_group_thread` change `group_id` `project_group_id` bigint(20) not null after `id`; + +alter table `project_group_thread` + add constraint fk_project_group_thread_project_group_id + foreign key (project_group_id) references project_group (id) + on delete cascade on update cascade; + +alter table `project_group_thread` + add constraint fk_project_group_thread_thread_id + foreign key (thread_id) references thread (id) + on delete cascade on update cascade; + +/* + * Step 24: forum_notification, Notification, NotificationData + */ + +-- table: forum_notification, + +alter table `forum_notification` drop foreign key `FK_forum_notification_notification_event`; +alter table `forum_notification` drop foreign key `FK_forum_notification_forum_post`; + +alter table `forum_notification` drop key `FK_forum_notification_notification_event`; + +alter table `forum_notification` drop primary key; + +alter table `forum_notification` change `forumPost_id` `forum_post_id` bigint(20) not null; +alter table `forum_notification` change `notificationEvent_id` `notification_data_id` bigint(20) not null; + +alter table `forum_notification` add primary key (forum_post_id, notification_data_id); + +alter table `forum_notification` + add constraint fk_forum_notification_forum_post_id + foreign key (forum_post_id) references forum_post (id) + on delete cascade on update cascade; + +-- table: Notification + +alter table `Notification` drop foreign key `FK_notification_user`; +alter table `Notification` drop foreign key `FK2D45DD0B599425F6`; + +alter table `Notification` drop key `FK2D45DD0B599425F6`; +alter table `Notification` drop key `FK2D45DD0B895349BF`; + +rename table `Notification` to `notification`; + +alter table `notification` change `mailed` `mailed` bit(1) not null after `version`; +alter table `notification` change `notificationData_id` `notification_data_id` bigint(20) default null; + +alter table `notification` + add constraint fk_notification_user_id + foreign key (user_id) references user (id) + on delete cascade on update cascade; + +-- table: NotificationData + +alter table `NotificationData` drop foreign key `FK_notification_data_user_caused_by`; +alter table `NotificationData` drop foreign key `FK_notification_data_project`; +alter table `NotificationData` drop foreign key `FK_notification_data_peer_review`; +alter table `NotificationData` drop foreign key `FK_notification_data_milestone`; +alter table `NotificationData` drop foreign key `FK_notification_data_group`; +alter table `NotificationData` drop foreign key `FK2DCAC355FCDADF61`; +alter table `NotificationData` drop foreign key `FK2DCAC3558D40D1B9`; +alter table `NotificationData` drop foreign key `FK2DCAC3554D07E0A9`; + +alter table `NotificationData` drop key `FK_notification_data_group`; +alter table `NotificationData` drop key `FK_notification_data_milestone`; +alter table `NotificationData` drop key `FK2DCAC355FCDADF61`; +alter table `NotificationData` drop key `FK2DCAC355B2E2AD78`; +alter table `NotificationData` drop key `FK2DCAC3558D40D1B9`; +alter table `NotificationData` drop key `FK2DCAC35542E9AC7B`; +alter table `NotificationData` drop key `FK2DCAC355C1813915`; +alter table `NotificationData` drop key `FK2DCAC3554D07E0A9`; + +rename table `NotificationData` to `notification_data`; + +alter table `notification_data` change `type` `type` varchar(255) default null after `event`; +alter table `notification_data` change `source` `source` longtext default null after `type`; +alter table `notification_data` change `additionalSource` `additional_source` longtext default null after `source`; +alter table `notification_data` change `DTYPE` `subclass` varchar(31) not null after `additional_source`; + +alter table `notification_data` change `seminar_id` `final_seminar_id` bigint(20) default null after `subclass`; +alter table `notification_data` change `idea_id` `idea_id` bigint(20) default null after `final_seminar_id`; +alter table `notification_data` change `mileStone_id` `milestone_id` bigint(20) default null after `idea_id`; +alter table `notification_data` change `request_id` `peer_request_id` bigint(20) default null after `milestone_id`; +alter table `notification_data` change `review_id` `peer_review_id` bigint(20) default null after `peer_request_id`; +alter table `notification_data` change `project_id` `project_id` bigint(20) default null after `peer_review_id`; +alter table `notification_data` change `group_id` `project_group_id` bigint(20) default null after `project_id`; +alter table `notification_data` change `causedBy_id` `caused_by_user_id` bigint(20) default null after `project_group_id`; + +alter table `notification_data` + add constraint fk_notification_data_final_seminar_id + foreign key (final_seminar_id) references final_seminar (id) + on delete cascade on update cascade; + +alter table `notification_data` + add constraint fk_notification_data_idea_id + foreign key (idea_id) references idea (id) + on delete cascade on update cascade; + +alter table `notification_data` + add constraint fk_notification_data_milestone_id + foreign key (milestone_id) references milestone (id) + on delete cascade on update cascade; + +alter table `notification_data` + add constraint fk_notification_data_peer_request_id + foreign key (peer_request_id) references peer_request (id) + on delete set null on update cascade; + +alter table `notification_data` + add constraint fk_notification_data_peer_review_id + foreign key (peer_review_id) references peer_review (id) + on delete cascade on update cascade; + +alter table `notification_data` + add constraint fk_notification_data_project_id + foreign key (project_id) references project (id) + on delete cascade on update cascade; + +alter table `notification_data` + add constraint fk_notification_data_project_group_id + foreign key (project_group_id) references project_group (id) + on delete cascade on update cascade; + +alter table `notification_data` + add constraint fk_notification_data_caused_by_user_id + foreign key (caused_by_user_id) references user (id) + on delete set null on update cascade; + +-- add foreign key from notification to notification_data + +alter table `notification` + add constraint fk_notification_notification_data_id + foreign key (notification_data_id) references notification_data (id) + on delete cascade on update cascade; + +-- add foreign key from forum_notification to notification_data + +alter table `forum_notification` + add constraint fk_forum_notification_notification_data_id + foreign key (notification_data_id) references notification_data (id) + on delete cascade on update cascade; diff --git a/core/src/test/java/se/su/dsv/scipro/milestones/service/MilestoneActivatorTest.java b/core/src/test/java/se/su/dsv/scipro/milestones/service/MilestoneActivatorTest.java index e42ccafdfc..fed52e8629 100644 --- a/core/src/test/java/se/su/dsv/scipro/milestones/service/MilestoneActivatorTest.java +++ b/core/src/test/java/se/su/dsv/scipro/milestones/service/MilestoneActivatorTest.java @@ -66,7 +66,7 @@ public class MilestoneActivatorTest { author.setId(123L); ProjectType bachelor = new ProjectType(DegreeType.BACHELOR, "Bachelor", "Bachelor"); - bachelor.getProjectTypeSettings().setMinimumActiveParticipationsToBeGraded(2); + bachelor.getProjectTypeSettings().setMinActiveParticipationsToBeGraded(2); project = Project.builder() .title("Project title") .projectType(bachelor) diff --git a/view/src/main/java/se/su/dsv/scipro/admin/panels/AdminProjectTypePanel.java b/view/src/main/java/se/su/dsv/scipro/admin/panels/AdminProjectTypePanel.java index ad084a3436..8284ab8966 100755 --- a/view/src/main/java/se/su/dsv/scipro/admin/panels/AdminProjectTypePanel.java +++ b/view/src/main/java/se/su/dsv/scipro/admin/panels/AdminProjectTypePanel.java @@ -54,16 +54,16 @@ public class AdminProjectTypePanel extends Panel { NumberTextField<Integer> minimumOppositionsToBeGraded = new NumberTextField<>( "minimum_oppositions_to_be_graded", LambdaModel.of(settings, - ProjectTypeSettings::getMinimumOppositionsToBeGraded, - ProjectTypeSettings::setMinimumOppositionsToBeGraded), + ProjectTypeSettings::getMinOppositionsToBeGraded, + ProjectTypeSettings::setMinOppositionsToBeGraded), Integer.class); minimumOppositionsToBeGraded.setMinimum(0); add(minimumOppositionsToBeGraded); NumberTextField<Integer> minimumActiveParticipationsToBeGraded = new NumberTextField<>( "minimum_active_participations_to_be_graded", LambdaModel.of(settings, - ProjectTypeSettings::getMinimumActiveParticipationsToBeGraded, - ProjectTypeSettings::setMinimumActiveParticipationsToBeGraded), + ProjectTypeSettings::getMinActiveParticipationsToBeGraded, + ProjectTypeSettings::setMinActiveParticipationsToBeGraded), Integer.class); minimumActiveParticipationsToBeGraded.setMinimum(0); add(minimumActiveParticipationsToBeGraded); diff --git a/view/src/main/java/se/su/dsv/scipro/checklists/AnswerPanel.java b/view/src/main/java/se/su/dsv/scipro/checklists/AnswerPanel.java index 5e54b3e4a9..a300022d1b 100644 --- a/view/src/main/java/se/su/dsv/scipro/checklists/AnswerPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/checklists/AnswerPanel.java @@ -27,7 +27,7 @@ public abstract class AnswerPanel extends Panel { ANSWER_IMAGES.put(ChecklistAnswerEnum.GREEN, "images/icons/bullet_ball_glass_green.png"); ANSWER_IMAGES.put(ChecklistAnswerEnum.YELLOW, "images/icons/bullet_ball_glass_yellow.png"); ANSWER_IMAGES.put(ChecklistAnswerEnum.RED, "images/icons/bullet_ball_glass_red.png"); - ANSWER_IMAGES.put(ChecklistAnswerEnum.NOT_APLICABLE, "images/icons/bullet_ball_glass_grey.png"); + ANSWER_IMAGES.put(ChecklistAnswerEnum.NOT_APPLICABLE, "images/icons/bullet_ball_glass_grey.png"); } public static final String CLICK_ICON = "images/icons/bullet_ball_glass_click.png"; diff --git a/view/src/main/java/se/su/dsv/scipro/checklists/ChecklistOverviewPanel.java b/view/src/main/java/se/su/dsv/scipro/checklists/ChecklistOverviewPanel.java index 1af096eee2..250d82e7e7 100644 --- a/view/src/main/java/se/su/dsv/scipro/checklists/ChecklistOverviewPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/checklists/ChecklistOverviewPanel.java @@ -55,7 +55,7 @@ public class ChecklistOverviewPanel extends GenericPanel<Project> { ChecklistAnswerEnum.GREEN, ChecklistAnswerEnum.YELLOW, ChecklistAnswerEnum.RED, - ChecklistAnswerEnum.NOT_APLICABLE); + ChecklistAnswerEnum.NOT_APPLICABLE); add(new ListView<>("answersBreakdown", answers) { @Override protected void populateItem(ListItem<ChecklistAnswerEnum> item) { diff --git a/view/src/main/java/se/su/dsv/scipro/checklists/ChecklistOverviewPanel.utf8.properties b/view/src/main/java/se/su/dsv/scipro/checklists/ChecklistOverviewPanel.utf8.properties index 9ad8928894..0d30f3ea89 100644 --- a/view/src/main/java/se/su/dsv/scipro/checklists/ChecklistOverviewPanel.utf8.properties +++ b/view/src/main/java/se/su/dsv/scipro/checklists/ChecklistOverviewPanel.utf8.properties @@ -1,4 +1,4 @@ ChecklistAnswerEnum.GREEN = Ok ChecklistAnswerEnum.YELLOW = Minor corrections ChecklistAnswerEnum.RED = Not done -ChecklistAnswerEnum.NOT_APLICABLE = Not applicable +ChecklistAnswerEnum.NOT_APPLICABLE = Not applicable diff --git a/view/src/main/java/se/su/dsv/scipro/checklists/TrafficLightPanel.java b/view/src/main/java/se/su/dsv/scipro/checklists/TrafficLightPanel.java index 51e779ba99..60482c38a8 100644 --- a/view/src/main/java/se/su/dsv/scipro/checklists/TrafficLightPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/checklists/TrafficLightPanel.java @@ -54,7 +54,7 @@ public class TrafficLightPanel extends FormComponentPanel<ChecklistAnswerEnum> { greenLink = new TrafficLightLink("greenLink", ChecklistAnswerEnum.GREEN, selectedGreen, greenImage); redLink = new TrafficLightLink("redLink", ChecklistAnswerEnum.RED, selectedRed, redImage); yellowLink = new TrafficLightLink("yellowLink", ChecklistAnswerEnum.YELLOW, selectedYellow, yellowImage); - noAnswerLink = new TrafficLightLink("noAnswerLink", ChecklistAnswerEnum.NOT_APLICABLE, selectedNotApplicable, noAnswerImage); + noAnswerLink = new TrafficLightLink("noAnswerLink", ChecklistAnswerEnum.NOT_APPLICABLE, selectedNotApplicable, noAnswerImage); add(greenLink); add(yellowLink); add(redLink); diff --git a/view/src/main/java/se/su/dsv/scipro/finalseminar/ProjectActiveParticipationListPanel.java b/view/src/main/java/se/su/dsv/scipro/finalseminar/ProjectActiveParticipationListPanel.java index 158b6ec5d9..40bb5744a8 100644 --- a/view/src/main/java/se/su/dsv/scipro/finalseminar/ProjectActiveParticipationListPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/finalseminar/ProjectActiveParticipationListPanel.java @@ -36,7 +36,7 @@ public class ProjectActiveParticipationListPanel extends GenericPanel<Project> { IModel<Integer> countRequired = model .map(Project::getProjectType) .map(ProjectType::getProjectTypeSettings) - .map(ProjectTypeSettings::getMinimumActiveParticipationsToBeGraded); + .map(ProjectTypeSettings::getMinActiveParticipationsToBeGraded); item.add(new Label("count_required", countRequired)); IModel<Long> countPerformed = participations.map(this::countApproved); item.add(new Label("count_approved", countPerformed)); diff --git a/view/src/main/java/se/su/dsv/scipro/grading/AbstractExaminationsPanel.java b/view/src/main/java/se/su/dsv/scipro/grading/AbstractExaminationsPanel.java index fbf8b36a5f..f24d065eb0 100644 --- a/view/src/main/java/se/su/dsv/scipro/grading/AbstractExaminationsPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/grading/AbstractExaminationsPanel.java @@ -213,8 +213,8 @@ abstract class AbstractExaminationsPanel extends GenericPanel<User> { .filter(FinalSeminarActiveParticipation::isApproved) .count(); final ProjectTypeSettings projectTypeSettings = project.getProjectType().getProjectTypeSettings(); - final int requiredOppositions = projectTypeSettings.getMinimumOppositionsToBeGraded(); - final int requiredActiveParticipations = projectTypeSettings.getMinimumActiveParticipationsToBeGraded(); + final int requiredOppositions = projectTypeSettings.getMinOppositionsToBeGraded(); + final int requiredActiveParticipations = projectTypeSettings.getMinActiveParticipationsToBeGraded(); return new SeminarParticipationGradingRequirements( new Requirement(requiredOppositions, completedOppositions), new Requirement(requiredActiveParticipations, completedParticipations)); diff --git a/view/src/main/java/se/su/dsv/scipro/grading/IndividualAuthorAssessmentPanel.java b/view/src/main/java/se/su/dsv/scipro/grading/IndividualAuthorAssessmentPanel.java index d76881782b..6dff147635 100644 --- a/view/src/main/java/se/su/dsv/scipro/grading/IndividualAuthorAssessmentPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/grading/IndividualAuthorAssessmentPanel.java @@ -128,7 +128,7 @@ public class IndividualAuthorAssessmentPanel extends GenericPanel<User> { IModel<Integer> minimumActiveParticipationsToBeGraded = LoadableDetachableModel.of(() -> { Project project = projectModel.getObject(); - return project.getProjectType().getProjectTypeSettings().getMinimumActiveParticipationsToBeGraded(); + return project.getProjectType().getProjectTypeSettings().getMinActiveParticipationsToBeGraded(); }); IModel<Integer> completedParticipations = LoadableDetachableModel.of(() -> { Project project = projectModel.getObject(); diff --git a/view/src/main/java/se/su/dsv/scipro/peer/DisplayQuestionPanel.java b/view/src/main/java/se/su/dsv/scipro/peer/DisplayQuestionPanel.java index 2c6818bb3e..7679a75eba 100644 --- a/view/src/main/java/se/su/dsv/scipro/peer/DisplayQuestionPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/peer/DisplayQuestionPanel.java @@ -38,7 +38,7 @@ public class DisplayQuestionPanel extends GenericPanel<Answer> { return "images/icons/bullet_ball_glass_red.png"; case GREEN: return "images/icons/bullet_ball_glass_green.png"; - case NOT_APLICABLE: + case NOT_APPLICABLE: return "images/icons/bullet_ball_glass_grey.png"; default: throw new IllegalStateException("unknown answer"); diff --git a/view/src/main/java/se/su/dsv/scipro/peer/DisplayQuestionPanel.properties b/view/src/main/java/se/su/dsv/scipro/peer/DisplayQuestionPanel.properties index 83808b9c7e..a2d4ad4158 100644 --- a/view/src/main/java/se/su/dsv/scipro/peer/DisplayQuestionPanel.properties +++ b/view/src/main/java/se/su/dsv/scipro/peer/DisplayQuestionPanel.properties @@ -2,4 +2,4 @@ no.motivation= No motivation written YELLOW= Minor corrections RED= Not done GREEN= Ok -NOT_APLICABLE= Not applicable \ No newline at end of file +NOT_APPLICABLE= Not applicable \ No newline at end of file diff --git a/view/src/test/java/se/su/dsv/scipro/checklists/TrafficLightPanelTest.java b/view/src/test/java/se/su/dsv/scipro/checklists/TrafficLightPanelTest.java index d8785aca19..b6c0e57856 100644 --- a/view/src/test/java/se/su/dsv/scipro/checklists/TrafficLightPanelTest.java +++ b/view/src/test/java/se/su/dsv/scipro/checklists/TrafficLightPanelTest.java @@ -25,7 +25,7 @@ public class TrafficLightPanelTest extends SciProTest { @Test public void renders_not_applicable() { - startPanel(Model.of(ChecklistAnswerEnum.NOT_APLICABLE)); + startPanel(Model.of(ChecklistAnswerEnum.NOT_APPLICABLE)); } @Test diff --git a/view/src/test/java/se/su/dsv/scipro/peer/DisplayQuestionPanelTest.java b/view/src/test/java/se/su/dsv/scipro/peer/DisplayQuestionPanelTest.java index 56212cd5d9..fbb66e7b45 100644 --- a/view/src/test/java/se/su/dsv/scipro/peer/DisplayQuestionPanelTest.java +++ b/view/src/test/java/se/su/dsv/scipro/peer/DisplayQuestionPanelTest.java @@ -28,7 +28,7 @@ public class DisplayQuestionPanelTest extends SciProTest { @Test public void renders_with_not_applicable_answer() { - startPanel(ChecklistAnswerEnum.NOT_APLICABLE, "motivation"); + startPanel(ChecklistAnswerEnum.NOT_APPLICABLE, "motivation"); } @Test From a9b85425768e99895d45e5f2d787454e5f328404 Mon Sep 17 00:00:00 2001 From: Andreas Svanberg <andreass@dsv.su.se> Date: Wed, 13 Nov 2024 08:01:17 +0100 Subject: [PATCH 4/8] Fix users getting stuck at a blank white page after logging in. (#16) By default, Tomcat will use a cookie to track the session. However, if there is no cookie sent by the browser it will append the session id to the URL. The way it does this is by adding a ";jsessionid=..." to the end. This is not a problem in itself, but it can enable session hijacking if the URL is shared and ";" is a blocked character by the default Spring Security configuration (see StrictHttpFirewall). So what happens is a user navigates to SciPro. No session cookie is sent since this is the first request. SciPro sees that the user is not authenticated and redirects the user to the login page. When SciPro checks for authentication it checks the session which will instruct Tomcat to create a session. Since Tomcat sees no cookie it will append the session id to the redirect URL to try and track the session. After the user has logged in they are redirected back to SciPro with the session id in the URL which is then blocked by Spring's StrictHttpFirewall. To avoid this, we can set the tracking mode to *only* COOKIE. An alternative solution is to tell Spring to allow ";" in the URL but there seems to be good reason as to why it is blocked, see the Javadoc linked below. https://github.com/spring-projects/spring-security/blob/ab93541926bef02f76231b78ba97ca0bed14c340/web/src/main/java/org/springframework/security/web/firewall/StrictHttpFirewall.java#L202 ## How to test 1. Open a new private browsing window (to make sure there are no cookies). 2. Go to http://localhost:8080 (or wherever you have SciPro running) while on the `develop` branch 3. See that you're stuck on a blank white page with a ";jsessionid=..." in the URL with a 401 response 4. Remove the ";jsessionid=..." part and you'll be logged in to SciPro 5. Switch to this branch and try and see that you'll be logged in immediately Reviewed-on: https://gitea.dsv.su.se/DMC/scipro/pulls/16 Reviewed-by: niat8586 <nico@dsv.su.se> Co-authored-by: Andreas Svanberg <andreass@dsv.su.se> Co-committed-by: Andreas Svanberg <andreass@dsv.su.se> --- war/src/main/webapp/WEB-INF/web.xml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/war/src/main/webapp/WEB-INF/web.xml b/war/src/main/webapp/WEB-INF/web.xml index b346f3b49c..9741e82487 100755 --- a/war/src/main/webapp/WEB-INF/web.xml +++ b/war/src/main/webapp/WEB-INF/web.xml @@ -10,5 +10,28 @@ <session-config> <session-timeout>480</session-timeout> + + <!-- + By default, Tomcat will use a cookie to track the session. + However, if there is no cookie sent by the browser it will append + the session id to the URL. The way it does this is by adding a + ";jsessionid=..." to the end. This is not a problem in itself, but + it can enable session hijacking if the URL is shared and ";" is + a blocked character by the default Spring Security configuration. + (see StrictHttpFirewall). + + So what happens is a user navigates to SciPro. No session cookie is + sent since this is the first request. SciPro sees that the user is + not authenticated and redirects the user to the login page. + When SciPro checks for authentication it checks the session which + will instruct Tomcat to create a session. Since Tomcat sees no + cookie it will append the session id to the redirect URL to try and + track the session. After the user has logged in it is redirected + back to SciPro with the session id in the URL which is then blocked + by Spring's StrictHttpFirewall. + + To avoid this, we can set the tracking mode to *only* COOKIE. + --> + <tracking-mode>COOKIE</tracking-mode> </session-config> </web-app> From d89417ceea935b26a3d51fc17002e09344bd8884 Mon Sep 17 00:00:00 2001 From: Nico Athanassiadis <nico@dsv.su.se> Date: Thu, 14 Nov 2024 12:39:41 +0100 Subject: [PATCH 5/8] Fix intermittent sorting of criterion to actual order (#18) When you tried to edit a grading template in "Project management" -> "Grading Templates" the criterion could be shown in an order not reflecting the sortOrder of the criterion. The reason was that we only got the arbitrary order depending on the insertion order in the database. Changed the Collection to a List, it is now an ArrayList. Also added @OrderBy("sortOrder ASC") to actually sort by the order of the criterion thus ensuring visual order is intact. Co-authored-by: Tom Zhao <tom.zhao@dsv.su.se> Reviewed-on: https://gitea.dsv.su.se/DMC/scipro/pulls/18 Reviewed-by: Tom Zhao <tom.zhao@dsv.su.se> Co-authored-by: Nico Athanassiadis <nico@dsv.su.se> Co-committed-by: Nico Athanassiadis <nico@dsv.su.se> --- .../java/se/su/dsv/scipro/report/GradingReportTemplate.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplate.java b/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplate.java index f8b5c9c8c3..55fe04823b 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplate.java +++ b/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplate.java @@ -10,6 +10,7 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.OneToMany; import jakarta.persistence.OneToOne; +import jakarta.persistence.OrderBy; import jakarta.persistence.Table; import jakarta.persistence.Temporal; import jakarta.persistence.TemporalType; @@ -22,7 +23,6 @@ import se.su.dsv.scipro.system.User; import java.time.LocalDate; import java.util.ArrayList; import java.util.Collection; -import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -62,7 +62,8 @@ public class GradingReportTemplate extends DomainObject { // JPA-mappings of other tables referencing to this table "grading_report_template" // ---------------------------------------------------------------------------------- @OneToMany(mappedBy = "gradingReportTemplate", cascade = {CascadeType.ALL}, orphanRemoval = true) - private Collection<GradingCriterionTemplate> criteria = new HashSet<>(); + @OrderBy("sortOrder ASC") + private List<GradingCriterionTemplate> criteria = new ArrayList<>(); @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "grading_report_template_id", referencedColumnName = "id") From 1f0f15fc18a56a45fdf98bc61c88e0958c5002d9 Mon Sep 17 00:00:00 2001 From: Tom Zhao <tom.zhao@dsv.su.se> Date: Tue, 19 Nov 2024 12:17:15 +0100 Subject: [PATCH 6/8] 3471: Reduced size of textarea as requested, also made small reformatting of Java code (#19) * number of rows in textarea is reduced from 20 to 7. * made small reformatting of ProjectNoteColumn Reviewed-on: https://gitea.dsv.su.se/DMC/scipro/pulls/19 Reviewed-by: ansv7779 <andreass@dsv.su.se> Co-authored-by: Tom Zhao <tom.zhao@dsv.su.se> Co-committed-by: Tom Zhao <tom.zhao@dsv.su.se> --- .../panels/ProjectNoteColumn$ViewAndEditNoteForm.html | 2 +- .../su/dsv/scipro/supervisor/panels/ProjectNoteColumn.java | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn$ViewAndEditNoteForm.html b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn$ViewAndEditNoteForm.html index bf546f6a76..13c72afcac 100644 --- a/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn$ViewAndEditNoteForm.html +++ b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn$ViewAndEditNoteForm.html @@ -6,7 +6,7 @@ <div wicket:id="feedback"></div> <div class="mb-3"> <label wicket:for="note" class="sr-only">Note</label> - <textarea wicket:id="note" rows="20" class="form-control"></textarea> + <textarea wicket:id="note" rows="7" class="form-control"></textarea> </div> <button wicket:id="save" type="submit" class="btn btn-primary">Save</button> </form> diff --git a/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn.java b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn.java index b35962f891..77424cf02a 100644 --- a/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn.java +++ b/view/src/main/java/se/su/dsv/scipro/supervisor/panels/ProjectNoteColumn.java @@ -51,11 +51,8 @@ public class ProjectNoteColumn extends AbstractExportableColumn<Project, String> } @Override - public void populateItem( - Item<ICellPopulator<Project>> cellItem, - String componentId, - IModel<Project> rowModel) - { + public void populateItem(Item<ICellPopulator<Project>> cellItem, String componentId, + IModel<Project> rowModel) { cellItem.add(new ViewAndEditNoteCellPanel(componentId, rowModel)); } From 73307096c36f4a012ff0325891a5e1700b6b3a74 Mon Sep 17 00:00:00 2001 From: Andreas Svanberg <andreass@dsv.su.se> Date: Wed, 20 Nov 2024 12:56:21 +0100 Subject: [PATCH 7/8] Fix some remaining issues from the Spring migration (#20) A few missing `@Bean` definitions were discovered. Spring also has a much stricter requirement about requiring `@Transactional` for every database change. ## How to test `@Bean GroupFacadeImpl` 1. Log in as a supervisor 2. Go to "My groups" and create a group 3. Go back to "My groups" and try to open the group ## How to test `@Bean IdeaFacadae` 1. Create an application period that is open ("Admin" / "Match" / "Application periods") 2. Log in as an author 3. Go to "Ideas" / "My ideas" 4. Click "Select from available ideas" in the period created in step 1 ## How to test missing `@Transactional` 1. Log in as a user with notifications (or generate some by for example writing in the forum) 2. Go to "Notifications" in the top right 3. Click on any notification subject to navigate to it ## How to test crash while trying to schedule final seminar 1. Log in as a supervisor 2. Open a project and attempt to schedule a final seminar ## How to test crash while trying to upload final thesis as supervisor 1. Log in as supervisor 2. Note down the supervisors username 3. Open a project that has had a final seminar 4. Go to the "Finishing up" tab 5. Submit the supervisors username as the custom principal 6. Try to upload a final thesis ## How to test removal of approved final thesis 1. Log in as supervisor 2. Note down the supervisors username 3. Open a project that has had a final seminar 4. Go to the "Finishing up" tab 5. Submit the supervisors username as the custom principal 6. Upload a final thesis 7. Approve the final thesis 8. Remove the approval ## How to test crash while trying to schedule first meeting 1. Log in as supervisor 2. Open a project 3. Go to the "First meeting tab" 4. Try to submit ## How to test crash while trying to unselect an idea as an author 1. Create an application period that is open ("Admin" / "Match" / "Application periods") 2. Log in as an author 3. Go to "Ideas" / "My ideas" 4. Click "Select from available ideas" in the period created in step 1 5. Select any available supervisor idea 6. Go back to "Ideas" / "My ideas" 7. Open the selected idea 8. Hit unselect at the bottom ## How to test crash while trying to toggle milestone 1. Log in as supervisor 2. Open any project 3. Go to "Milestones" tab 4. Attempt to toggle both individual and project milestones ## How to test crash while trying to get user's note 1. Find a user without a row in the `note` table 2. Log in as that user 3. Click "My notes" in the top right Reviewed-on: https://gitea.dsv.su.se/DMC/scipro/pulls/20 Reviewed-by: Nico Athanassiadis <nico@dsv.su.se> Co-authored-by: Andreas Svanberg <andreass@dsv.su.se> Co-committed-by: Andreas Svanberg <andreass@dsv.su.se> --- core/src/main/java/se/su/dsv/scipro/CoreConfig.java | 12 ++++++++++++ .../FinalSeminarRespondentServiceImpl.java | 2 ++ .../scipro/finalthesis/FinalThesisServiceImpl.java | 2 ++ .../scipro/firstmeeting/FirstMeetingServiceImpl.java | 2 ++ .../java/se/su/dsv/scipro/match/IdeaServiceImpl.java | 3 +-- .../service/impl/MilestoneServiceImpl.java | 3 +++ .../java/se/su/dsv/scipro/notes/NoteServiceImpl.java | 2 ++ .../notifications/NotificationServiceImpl.java | 2 ++ .../dsv/scipro/report/GradingReportServiceImpl.java | 1 + .../se/su/dsv/scipro/report/ReportServiceImpl.java | 2 ++ .../reviewing/ReviewerInteractionServiceImpl.java | 1 + .../dsv/scipro/reviewing/ReviewingServiceImpl.java | 3 +++ .../serviceimpls/UserProfileServiceImpl.java | 1 + .../dsv/scipro/system/ResearchAreaServiceImpl.java | 3 +++ 14 files changed, 37 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/se/su/dsv/scipro/CoreConfig.java b/core/src/main/java/se/su/dsv/scipro/CoreConfig.java index d9245d2155..a6ec1b8ffe 100644 --- a/core/src/main/java/se/su/dsv/scipro/CoreConfig.java +++ b/core/src/main/java/se/su/dsv/scipro/CoreConfig.java @@ -65,6 +65,7 @@ import se.su.dsv.scipro.grading.NationalSubjectCategoryServiceImpl; import se.su.dsv.scipro.grading.PublicationMetadataRepository; import se.su.dsv.scipro.grading.PublicationMetadataServiceImpl; import se.su.dsv.scipro.grading.ThesisSubmissionHistoryService; +import se.su.dsv.scipro.group.GroupFacadeImpl; import se.su.dsv.scipro.group.GroupService; import se.su.dsv.scipro.group.GroupServiceImpl; import se.su.dsv.scipro.integration.activityfinalseminar.ActivityFinalSeminarRepository; @@ -79,6 +80,7 @@ import se.su.dsv.scipro.match.ApplicationPeriodProjectTypeServiceImpl; import se.su.dsv.scipro.match.ApplicationPeriodService; import se.su.dsv.scipro.match.ApplicationPeriodServiceImpl; import se.su.dsv.scipro.match.FirstMeetingRepository; +import se.su.dsv.scipro.match.IdeaFacade; import se.su.dsv.scipro.match.IdeaRepository; import se.su.dsv.scipro.match.IdeaService; import se.su.dsv.scipro.match.IdeaServiceImpl; @@ -1009,4 +1011,14 @@ public class CoreConfig { public NotificationEventServiceImpl notificationEventService(NotificationEventRepository notificationEventRepository) { return new NotificationEventServiceImpl(notificationEventRepository); } + + @Bean + public IdeaFacade ideaFacade() { + return new IdeaFacade(); + } + + @Bean + public GroupFacadeImpl groupFacade() { + return new GroupFacadeImpl(); + } } diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarRespondentServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarRespondentServiceImpl.java index ee7478c33c..f532f0289d 100644 --- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarRespondentServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarRespondentServiceImpl.java @@ -1,5 +1,6 @@ package se.su.dsv.scipro.finalseminar; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.AbstractServiceImpl; import se.su.dsv.scipro.system.User; @@ -33,6 +34,7 @@ public class FinalSeminarRespondentServiceImpl extends AbstractServiceImpl<Final } @Override + @Transactional public List<FinalSeminarRespondent> findOrCreate(FinalSeminar finalSeminar) { if(finalSeminar.getId() == null) { return new ArrayList<>(); diff --git a/core/src/main/java/se/su/dsv/scipro/finalthesis/FinalThesisServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/finalthesis/FinalThesisServiceImpl.java index 41251d1700..f505a3d189 100644 --- a/core/src/main/java/se/su/dsv/scipro/finalthesis/FinalThesisServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/finalthesis/FinalThesisServiceImpl.java @@ -56,6 +56,7 @@ public class FinalThesisServiceImpl extends AbstractServiceImpl<FinalThesis, Lon } @Override + @Transactional public FinalThesis upload(ProjectFileUpload fileUpload, String englishTitle, String swedishTitle) { ProjectFile fileDescription = storeFinalThesisFile(fileUpload); final FileReference reference = fileService.createReference(fileDescription.getFileDescription()); @@ -133,6 +134,7 @@ public class FinalThesisServiceImpl extends AbstractServiceImpl<FinalThesis, Lon } @Override + @Transactional public void removeApproval(Project project) { setStatus(project, FinalThesis.Status.NO_DECISION); } diff --git a/core/src/main/java/se/su/dsv/scipro/firstmeeting/FirstMeetingServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/firstmeeting/FirstMeetingServiceImpl.java index 23d1832201..1ab1e575a8 100644 --- a/core/src/main/java/se/su/dsv/scipro/firstmeeting/FirstMeetingServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/firstmeeting/FirstMeetingServiceImpl.java @@ -1,5 +1,6 @@ package se.su.dsv.scipro.firstmeeting; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.activityplan.Activity; import se.su.dsv.scipro.activityplan.ActivityPlanFacade; import se.su.dsv.scipro.project.Project; @@ -26,6 +27,7 @@ public class FirstMeetingServiceImpl extends AbstractServiceImpl<ProjectFirstMee } @Override + @Transactional public ProjectFirstMeeting schedule(final Project project, final Date date, final String room, final String description) { final Optional<ProjectFirstMeeting> optFirstMeeting = findByProject(project); final ProjectFirstMeeting firstMeeting = optFirstMeeting diff --git a/core/src/main/java/se/su/dsv/scipro/match/IdeaServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/match/IdeaServiceImpl.java index d3c410eb05..e6be18e1c3 100755 --- a/core/src/main/java/se/su/dsv/scipro/match/IdeaServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/match/IdeaServiceImpl.java @@ -358,7 +358,6 @@ public class IdeaServiceImpl extends AbstractServiceImpl<Idea, Long> implements } } - @Transactional private Idea acceptIdea0(Idea idea, User creator, Program accepteeProgram, User coAuthor, final ApplicationPeriod applicationPeriod) { Idea localIdea = idea; @@ -442,6 +441,7 @@ public class IdeaServiceImpl extends AbstractServiceImpl<Idea, Long> implements } @Override + @Transactional public void studentUnselect(final Idea idea, final User student) { unmatch(idea, student, new NotificationSource()); } @@ -490,7 +490,6 @@ public class IdeaServiceImpl extends AbstractServiceImpl<Idea, Long> implements return returnValue; } - @Transactional private Idea addMatch(User creator, User supervisor, Idea idea, NotificationSource notificationSource) { Match match = new Match(); match.setIdea(idea); diff --git a/core/src/main/java/se/su/dsv/scipro/milestones/service/impl/MilestoneServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/milestones/service/impl/MilestoneServiceImpl.java index 70c69ddef2..f7b5b8c447 100644 --- a/core/src/main/java/se/su/dsv/scipro/milestones/service/impl/MilestoneServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/milestones/service/impl/MilestoneServiceImpl.java @@ -4,6 +4,7 @@ import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Predicate; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQuery; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.Pageable; import se.su.dsv.scipro.milestones.dataobjects.Milestone; import se.su.dsv.scipro.milestones.dataobjects.MilestoneActivityTemplate; @@ -54,6 +55,7 @@ public class MilestoneServiceImpl extends AbstractServiceImpl<Milestone, Long> i } @Override + @Transactional public void setConfirmed(Project project, MilestoneActivityTemplate activity, boolean confirmed) { if (confirmed) { for (MilestoneActivityTemplate earlierActivity : getEarlierIncompleteProjectMilestoneActivities(project, activity)) { @@ -84,6 +86,7 @@ public class MilestoneServiceImpl extends AbstractServiceImpl<Milestone, Long> i } @Override + @Transactional public void setConfirmed(Project project, User student, MilestoneActivityTemplate activity, boolean confirmed) { if (!project.hasModule(ProjectModule.MILESTONES)) { diff --git a/core/src/main/java/se/su/dsv/scipro/notes/NoteServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/notes/NoteServiceImpl.java index 126470035e..58cb33dbc1 100755 --- a/core/src/main/java/se/su/dsv/scipro/notes/NoteServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/notes/NoteServiceImpl.java @@ -1,6 +1,7 @@ package se.su.dsv.scipro.notes; import com.querydsl.core.types.dsl.BooleanExpression; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.system.AbstractServiceImpl; import se.su.dsv.scipro.system.User; @@ -20,6 +21,7 @@ public class NoteServiceImpl extends AbstractServiceImpl<Note, Long> implements } @Override + @Transactional public Note getNote(User user) { Note note = findOne(hasUser(user)); if (note == null){ diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/NotificationServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/notifications/NotificationServiceImpl.java index 6c460a0741..5bbe68093e 100755 --- a/core/src/main/java/se/su/dsv/scipro/notifications/NotificationServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/NotificationServiceImpl.java @@ -50,6 +50,7 @@ public class NotificationServiceImpl extends AbstractServiceImpl<Notification,Lo } @Override + @Transactional public void setRead(User user, NotificationEvent notificationEvent, boolean read) { Iterable<Notification> notifications = findAll( QNotification.notification.notificationEvent.eq(notificationEvent) @@ -62,6 +63,7 @@ public class NotificationServiceImpl extends AbstractServiceImpl<Notification,Lo } @Override + @Transactional @SuppressWarnings("unchecked") // This looks so wrong but a List<Notification> is what we actually get // during runtime, see SCIPRO-167935. Reflection so awesome... diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradingReportServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/report/GradingReportServiceImpl.java index 1dd53e1665..876d3a4010 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/GradingReportServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/report/GradingReportServiceImpl.java @@ -48,6 +48,7 @@ public class GradingReportServiceImpl implements GradingReportTemplateService, G } @Override + @Transactional public boolean updateOppositionCriteria(SupervisorGradingReport report, FinalSeminarOpposition opposition) { for (GradingCriterion gradingCriterion : report.getIndividualCriteria()) { boolean isOppositionCriterion = gradingCriterion.getFlag() == GradingCriterion.Flag.OPPOSITION; diff --git a/core/src/main/java/se/su/dsv/scipro/report/ReportServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/report/ReportServiceImpl.java index 44d938d819..a0f324029f 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/ReportServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/report/ReportServiceImpl.java @@ -22,12 +22,14 @@ public class ReportServiceImpl extends AbstractServiceImpl<Report, Long> impleme } @Override + @Transactional public AttachmentReport submit(AttachmentReport report) { report.submit(); return save(report); } @Override + @Transactional public void save(AttachmentReport report, Optional<FileUpload> fileUpload) { storeReportFile(report, fileUpload); save(report); diff --git a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerInteractionServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerInteractionServiceImpl.java index a08f5ffcbc..f0e62aacc6 100644 --- a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerInteractionServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewerInteractionServiceImpl.java @@ -49,6 +49,7 @@ public class ReviewerInteractionServiceImpl implements ReviewerInteractionServic } @Override + @Transactional public ForumPost reply(final Project project, final User user, final String content, final Set<Attachment> attachments) { ReviewerThread reviewerThread = getReviewerThread(project); ForumPost reply = forumService.createReply(reviewerThread.getForumThread(), user, content, attachments); diff --git a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewingServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewingServiceImpl.java index 9087510e37..b56e733c68 100644 --- a/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewingServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/reviewing/ReviewingServiceImpl.java @@ -7,6 +7,7 @@ import com.querydsl.core.types.Predicate; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.LiteralExpression; import com.querydsl.jpa.impl.JPAQuery; +import jakarta.transaction.Transactional; import se.su.dsv.scipro.file.FileReference; import se.su.dsv.scipro.file.FileService; import se.su.dsv.scipro.file.FileUpload; @@ -92,6 +93,7 @@ public class ReviewingServiceImpl extends AbstractServiceImpl<ReviewerApproval, } @Override + @Transactional public void reject(final ReviewerApproval reviewerApproval, final String reason, final Optional<FileUpload> feedback) { Optional<FileReference> feedbackFile = store(feedback); reviewerApproval.reject(reason, feedbackFile); @@ -106,6 +108,7 @@ public class ReviewingServiceImpl extends AbstractServiceImpl<ReviewerApproval, } @Override + @Transactional public void approve(final ReviewerApproval process, final String reason, final Optional<FileUpload> feedback) { Optional<FileReference> feedbackFile = store(feedback); process.approve(reason, feedbackFile); diff --git a/core/src/main/java/se/su/dsv/scipro/springdata/serviceimpls/UserProfileServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/springdata/serviceimpls/UserProfileServiceImpl.java index 788ae44b07..992aa54888 100644 --- a/core/src/main/java/se/su/dsv/scipro/springdata/serviceimpls/UserProfileServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/springdata/serviceimpls/UserProfileServiceImpl.java @@ -38,6 +38,7 @@ public class UserProfileServiceImpl extends AbstractServiceImpl<UserProfile, Lon } @Override + @Transactional public Roles findSelectedRole(User user) { return findByUser(user).getSelectedRole(); } diff --git a/core/src/main/java/se/su/dsv/scipro/system/ResearchAreaServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/system/ResearchAreaServiceImpl.java index 76dc29c854..3c75c66915 100755 --- a/core/src/main/java/se/su/dsv/scipro/system/ResearchAreaServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/system/ResearchAreaServiceImpl.java @@ -3,6 +3,8 @@ package se.su.dsv.scipro.system; import jakarta.inject.Inject; import jakarta.inject.Provider; import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; + import java.util.Comparator; import java.util.List; @@ -13,6 +15,7 @@ public class ResearchAreaServiceImpl extends AbstractServiceImpl<ResearchArea,Lo } @Override + @Transactional public ResearchArea updateExternalResearchArea(Long identifier, String name, final boolean active) { ResearchArea ra = new ResearchArea(); if (identifier != null) { From ff4c5b58b40db5fcb7754c259c3854194668c1e1 Mon Sep 17 00:00:00 2001 From: Andreas Svanberg <andreass@dsv.su.se> Date: Thu, 21 Nov 2024 19:20:47 +0100 Subject: [PATCH 8/8] Allow changes to the reflection to be made after it's been submitted (#13) Replaces #12 Fixes card 3213 and 3412 There are minimum requirements for the reflection document submitted by authors at the end of the thesis process. Before now there was no way to handle the case when the reflection did not meet these minimum requirements. This change makes it possible in two ways; 1. The supervisor can request improvements to be made requiring the author to re-submit a new reflection inside SciPro 2. The supervisor can directly edit the reflection themselves if it has been submitted out-of-band or for any other reason Co-authored-by: Nico Athanassiadis <nico@dsv.su.se> Reviewed-on: https://gitea.dsv.su.se/DMC/scipro/pulls/13 Reviewed-by: Nico Athanassiadis <nico@dsv.su.se> --- .../java/se/su/dsv/scipro/CoreConfig.java | 5 +- .../dataobject/ProjectEvent.java | 3 +- .../notifications/notifications.properties | 7 + .../java/se/su/dsv/scipro/project/Author.java | 27 +++ .../dsv/scipro/project/ReflectionStatus.java | 7 + .../su/dsv/scipro/reflection/Reflection.java | 22 ++ .../ReflectionImprovementsRequestedEvent.java | 7 + .../ReflectionImprovementsSubmittedEvent.java | 10 + .../scipro/reflection/ReflectionService.java | 11 + .../reflection/ReflectionServiceImpl.java | 59 +++++- .../V392_1__reflection_resubmission.sql | 4 + ...92_2__reflection_comment_by_supervisor.sql | 1 + .../reflection/ReflectionServiceTest.java | 20 ++ .../crosscutting/NotifyFailedReflection.java | 46 +++++ .../su/dsv/scipro/grading/CriteriaPanel.html | 10 +- .../su/dsv/scipro/grading/CriteriaPanel.java | 27 ++- .../grading/ReflectionModalBodyPanel.html | 82 ++++++++ .../grading/ReflectionModalBodyPanel.java | 191 ++++++++++++++++++ .../ReflectionModalBodyPanel.utf8.properties | 10 + .../pages/NotificationLandingPage.java | 2 +- .../project/panels/FinalStepsPanel.html | 24 +++ .../project/panels/FinalStepsPanel.java | 58 +++++- .../panels/FinalStepsPanel.utf8.properties | 5 + .../dsv/scipro/wicket-package.utf8.properties | 2 + .../java/se/su/dsv/scipro/SciProTest.java | 3 + .../dsv/scipro/war/WicketConfiguration.java | 10 + 26 files changed, 628 insertions(+), 25 deletions(-) create mode 100644 core/src/main/java/se/su/dsv/scipro/project/ReflectionStatus.java create mode 100644 core/src/main/java/se/su/dsv/scipro/reflection/Reflection.java create mode 100644 core/src/main/java/se/su/dsv/scipro/reflection/ReflectionImprovementsRequestedEvent.java create mode 100644 core/src/main/java/se/su/dsv/scipro/reflection/ReflectionImprovementsSubmittedEvent.java create mode 100644 core/src/main/resources/db/migration/V392_1__reflection_resubmission.sql create mode 100644 core/src/main/resources/db/migration/V392_2__reflection_comment_by_supervisor.sql create mode 100644 view/src/main/java/se/su/dsv/scipro/crosscutting/NotifyFailedReflection.java create mode 100644 view/src/main/java/se/su/dsv/scipro/grading/ReflectionModalBodyPanel.html create mode 100644 view/src/main/java/se/su/dsv/scipro/grading/ReflectionModalBodyPanel.java create mode 100644 view/src/main/java/se/su/dsv/scipro/grading/ReflectionModalBodyPanel.utf8.properties diff --git a/core/src/main/java/se/su/dsv/scipro/CoreConfig.java b/core/src/main/java/se/su/dsv/scipro/CoreConfig.java index a6ec1b8ffe..918df6478f 100644 --- a/core/src/main/java/se/su/dsv/scipro/CoreConfig.java +++ b/core/src/main/java/se/su/dsv/scipro/CoreConfig.java @@ -744,9 +744,10 @@ public class CoreConfig { @Bean public ReflectionServiceImpl reflectionService( AuthorRepository authorRepository, - FinalSeminarServiceImpl finalSeminarService) + FinalSeminarServiceImpl finalSeminarService, + EventBus eventBus) { - return new ReflectionServiceImpl(authorRepository, finalSeminarService); + return new ReflectionServiceImpl(authorRepository, finalSeminarService, eventBus); } @Bean diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/ProjectEvent.java b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/ProjectEvent.java index a44a3760be..ae72d48f16 100755 --- a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/ProjectEvent.java +++ b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/ProjectEvent.java @@ -23,7 +23,8 @@ public class ProjectEvent extends NotificationEvent { ROUGH_DRAFT_APPROVAL_APPROVED, ROUGH_DRAFT_APPROVAL_REJECTED, REVIEWER_GRADING_REPORT_SUBMITTED, ONE_YEAR_PASSED_FROM_LATEST_ANNUAL_REVIEW, SUPERVISOR_GRADING_INITIAL_ASSESSMENT_DONE, EXPORTED_SUCCESS, REVIEWER_GRADING_INITIAL_ASSESSMENT_DONE, FIRST_MEETING, OPPOSITION_FAILED, - PARTICIPATION_APPROVED, COMPLETED, PARTICIPATION_FAILED + PARTICIPATION_APPROVED, COMPLETED, PARTICIPATION_FAILED, REFLECTION_IMPROVEMENTS_REQUESTED, + REFLECTION_IMPROVEMENTS_SUBMITTED } @Basic diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/notifications.properties b/core/src/main/java/se/su/dsv/scipro/notifications/notifications.properties index a972eac30e..c5cb11b76a 100755 --- a/core/src/main/java/se/su/dsv/scipro/notifications/notifications.properties +++ b/core/src/main/java/se/su/dsv/scipro/notifications/notifications.properties @@ -85,6 +85,13 @@ PROJECT.PARTICIPATION_APPROVED.body = Your active participation on {0} has been PROJECT.PARTICIPATION_FAILED.title = Your active participation on {1} did not meet the minimum requirements. PROJECT.PARTICIPATION_FAILED.body = Your active participation did not meet the minimum requirements set, and you will \ have to be an active participant on a different final seminar to pass this step. +PROJECT.REFLECTION_IMPROVEMENTS_REQUESTED.title = Reflection improvements requested +PROJECT.REFLECTION_IMPROVEMENTS_REQUESTED.body = The supervisor has deemed that the reflection submitted does not meet \ + the minimum requirements and has requested improvements. Please log into SciPro and submit a new reflection. \ + Their comments can be seen below:\n\n{0} +PROJECT.REFLECTION_IMPROVEMENTS_SUBMITTED.title = Reflection improvements submitted +PROJECT.REFLECTION_IMPROVEMENTS_SUBMITTED.body = The reflection improvements have been submitted. \ + \n\n{0} FORUM.NEW_FORUM_POST.title = Forum post: {2} FORUM.NEW_FORUM_POST.body = New forum post submitted:<br /><br />{0} diff --git a/core/src/main/java/se/su/dsv/scipro/project/Author.java b/core/src/main/java/se/su/dsv/scipro/project/Author.java index 8adaa5fed3..96ec7ce284 100644 --- a/core/src/main/java/se/su/dsv/scipro/project/Author.java +++ b/core/src/main/java/se/su/dsv/scipro/project/Author.java @@ -5,6 +5,8 @@ import jakarta.persistence.Column; import jakarta.persistence.Embeddable; import jakarta.persistence.EmbeddedId; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.MapsId; @@ -30,6 +32,15 @@ public class Author { @Column(name = "reflection") private String reflection; + @Basic + @Enumerated(EnumType.STRING) + @Column(name = "reflection_status") + private ReflectionStatus reflectionStatus = ReflectionStatus.NOT_SUBMITTED; + + @Basic + @Column(name = "reflection_comment_by_supervisor") + private String reflectionSupervisorComment; + /** * If this author wants to be notified when a final seminar created * as long as they have not yet completed both an opposition and @@ -85,6 +96,22 @@ public class Author { return user; } + public ReflectionStatus getReflectionStatus() { + return reflectionStatus; + } + + public void setReflectionStatus(ReflectionStatus reflectionStatus) { + this.reflectionStatus = reflectionStatus; + } + + public void setReflectionSupervisorComment(String reflectionSupervisorComment) { + this.reflectionSupervisorComment = reflectionSupervisorComment; + } + + public String getReflectionSupervisorComment() { + return reflectionSupervisorComment; + } + // ---------------------------------------------------------------------------------- // Nested class // ---------------------------------------------------------------------------------- diff --git a/core/src/main/java/se/su/dsv/scipro/project/ReflectionStatus.java b/core/src/main/java/se/su/dsv/scipro/project/ReflectionStatus.java new file mode 100644 index 0000000000..92b94cd7b6 --- /dev/null +++ b/core/src/main/java/se/su/dsv/scipro/project/ReflectionStatus.java @@ -0,0 +1,7 @@ +package se.su.dsv.scipro.project; + +public enum ReflectionStatus { + NOT_SUBMITTED, + SUBMITTED, + IMPROVEMENTS_NEEDED +} diff --git a/core/src/main/java/se/su/dsv/scipro/reflection/Reflection.java b/core/src/main/java/se/su/dsv/scipro/reflection/Reflection.java new file mode 100644 index 0000000000..898d961a2c --- /dev/null +++ b/core/src/main/java/se/su/dsv/scipro/reflection/Reflection.java @@ -0,0 +1,22 @@ +package se.su.dsv.scipro.reflection; + +public sealed interface Reflection { + boolean isSubmittable(); + + record NotSubmitted() implements Reflection { + @Override + public boolean isSubmittable() { return true; } + } + + record Submitted(String reflection) implements Reflection { + @Override + public boolean isSubmittable() { + return false; + } + } + + record ImprovementsNeeded(String oldReflection, String commentBySupervisor) implements Reflection { + @Override + public boolean isSubmittable() { return true; } + } +} diff --git a/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionImprovementsRequestedEvent.java b/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionImprovementsRequestedEvent.java new file mode 100644 index 0000000000..07d8811f99 --- /dev/null +++ b/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionImprovementsRequestedEvent.java @@ -0,0 +1,7 @@ +package se.su.dsv.scipro.reflection; + +import se.su.dsv.scipro.project.Project; +import se.su.dsv.scipro.system.User; + +public record ReflectionImprovementsRequestedEvent(Project project, User author, String supervisorComment) { +} diff --git a/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionImprovementsSubmittedEvent.java b/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionImprovementsSubmittedEvent.java new file mode 100644 index 0000000000..ce43d5eed4 --- /dev/null +++ b/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionImprovementsSubmittedEvent.java @@ -0,0 +1,10 @@ +package se.su.dsv.scipro.reflection; + +import se.su.dsv.scipro.project.Project; +import se.su.dsv.scipro.system.User; + +/** + * This event may be triggered by the supervisor if they edit the reflection after requesting improvements. + */ +public record ReflectionImprovementsSubmittedEvent(Project project, User author, String reflection) { +} diff --git a/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionService.java b/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionService.java index b4a206bf76..139dc9a6d9 100644 --- a/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionService.java +++ b/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionService.java @@ -14,4 +14,15 @@ public interface ReflectionService { * @return the reflection, or {@code null} if none has been submitted */ String getSubmittedReflection(Project project, User author); + + /** + * Used by the supervisor when the currently submitted reflection does not meet the minimum requirements. + * This is done individually by author. + * + * @param author the author whose reflection does not meet the minimum requirements. + * @param supervisorComment feedback provided by the supervisor so the author knows what to improve. + */ + void requestNewReflection(Project project, User author, String supervisorComment); + + Reflection getReflection(Project project, User author); } diff --git a/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionServiceImpl.java index bdc36bc904..73d934ca32 100644 --- a/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionServiceImpl.java @@ -1,22 +1,32 @@ package se.su.dsv.scipro.reflection; +import com.google.common.eventbus.EventBus; import jakarta.transaction.Transactional; import se.su.dsv.scipro.finalseminar.AuthorRepository; import se.su.dsv.scipro.finalseminar.FinalSeminarService; import se.su.dsv.scipro.project.Author; import se.su.dsv.scipro.project.Project; +import se.su.dsv.scipro.project.ReflectionStatus; import se.su.dsv.scipro.system.User; import jakarta.inject.Inject; +import java.util.Optional; + public class ReflectionServiceImpl implements ReflectionService { private final AuthorRepository authorRepository; private final FinalSeminarService finalSeminarService; + private final EventBus eventBus; @Inject - public ReflectionServiceImpl(AuthorRepository authorRepository, FinalSeminarService finalSeminarService) { + public ReflectionServiceImpl( + AuthorRepository authorRepository, + FinalSeminarService finalSeminarService, + EventBus eventBus) + { this.authorRepository = authorRepository; this.finalSeminarService = finalSeminarService; + this.eventBus = eventBus; } @Override @@ -25,10 +35,13 @@ public class ReflectionServiceImpl implements ReflectionService { } @Override - public boolean hasToFillInReflection(Project project, User author) { - boolean noReflectionSubmitted = authorRepository.findByProjectAndUser(project, author) - .map(Author::getReflection) - .isEmpty(); + public boolean hasToFillInReflection(Project project, User user) { + Optional<Author> optionalAuthor = authorRepository.findByProjectAndUser(project, user); + if (optionalAuthor.isEmpty()) { + return false; + } + Author author = optionalAuthor.get(); + boolean noReflectionSubmitted = author.getReflectionStatus() != ReflectionStatus.SUBMITTED; return hasReachedReflectionProcess(project) && noReflectionSubmitted; } @@ -36,7 +49,13 @@ public class ReflectionServiceImpl implements ReflectionService { @Transactional public void submitReflection(Project project, User user, String reflection) { authorRepository.findByProjectAndUser(project, user) - .ifPresent(author -> author.setReflection(reflection)); + .ifPresent(author -> { + if (author.getReflectionStatus() == ReflectionStatus.IMPROVEMENTS_NEEDED) { + eventBus.post(new ReflectionImprovementsSubmittedEvent(project, user, reflection)); + } + author.setReflection(reflection); + author.setReflectionStatus(ReflectionStatus.SUBMITTED); + }); } @Override @@ -45,4 +64,32 @@ public class ReflectionServiceImpl implements ReflectionService { .map(Author::getReflection) .orElse(null); } + + @Override + @Transactional + public void requestNewReflection(Project project, User user, String supervisorComment) { + authorRepository.findByProjectAndUser(project, user) + .ifPresent(author -> { + author.setReflectionStatus(ReflectionStatus.IMPROVEMENTS_NEEDED); + author.setReflectionSupervisorComment(supervisorComment); + }); + eventBus.post(new ReflectionImprovementsRequestedEvent(project, user, supervisorComment)); + } + + @Override + public Reflection getReflection(Project project, User author) { + return authorRepository.findByProjectAndUser(project, author) + .map(this::toReflection) + .orElseGet(Reflection.NotSubmitted::new); + } + + private Reflection toReflection(Author author) { + return switch (author.getReflectionStatus()) { + case SUBMITTED -> new Reflection.Submitted(author.getReflection()); + case IMPROVEMENTS_NEEDED -> new Reflection.ImprovementsNeeded( + author.getReflection(), + author.getReflectionSupervisorComment()); + default -> new Reflection.NotSubmitted(); + }; + } } diff --git a/core/src/main/resources/db/migration/V392_1__reflection_resubmission.sql b/core/src/main/resources/db/migration/V392_1__reflection_resubmission.sql new file mode 100644 index 0000000000..d80e266c9d --- /dev/null +++ b/core/src/main/resources/db/migration/V392_1__reflection_resubmission.sql @@ -0,0 +1,4 @@ +ALTER TABLE `project_user` + ADD COLUMN `reflection_status` VARCHAR(32) NOT NULL DEFAULT 'NOT_SUBMITTED'; + +UPDATE `project_user` SET `reflection_status` = 'SUBMITTED' WHERE `reflection` IS NOT NULL; diff --git a/core/src/main/resources/db/migration/V392_2__reflection_comment_by_supervisor.sql b/core/src/main/resources/db/migration/V392_2__reflection_comment_by_supervisor.sql new file mode 100644 index 0000000000..f3cc5f2ce1 --- /dev/null +++ b/core/src/main/resources/db/migration/V392_2__reflection_comment_by_supervisor.sql @@ -0,0 +1 @@ +ALTER TABLE `project_user` ADD COLUMN `reflection_comment_by_supervisor` TEXT NULL; diff --git a/core/src/test/java/se/su/dsv/scipro/reflection/ReflectionServiceTest.java b/core/src/test/java/se/su/dsv/scipro/reflection/ReflectionServiceTest.java index 8d8d462e31..745def4bcd 100644 --- a/core/src/test/java/se/su/dsv/scipro/reflection/ReflectionServiceTest.java +++ b/core/src/test/java/se/su/dsv/scipro/reflection/ReflectionServiceTest.java @@ -101,6 +101,26 @@ public class ReflectionServiceTest extends IntegrationTest { assertTrue(reflectionService.hasReachedReflectionProcess(project)); } + @Test + public void request_resubmission() { + LocalDate seminarDate = scheduleSeminar(); + clock.setDate(seminarDate.plusDays(1)); + assertTrue(reflectionService.hasToFillInReflection(project, author), + "After the final seminar the author should be required to submit a reflection"); + + String myReflection = "my reflection"; + reflectionService.submitReflection(project, author, myReflection); + assertEquals(myReflection, reflectionService.getSubmittedReflection(project, author)); + assertFalse(reflectionService.hasToFillInReflection(project, author), + "After submitting the initial reflection it should no longer be required"); + + reflectionService.requestNewReflection(project, author, "Very bad reflection"); + assertTrue(reflectionService.hasToFillInReflection(project, author), + "After supervisor requests resubmission the author should now be required to submit a new reflection"); + assertEquals(myReflection, reflectionService.getSubmittedReflection(project, author), + "The old reflection should be saved to make it easier for the student to update it"); + } + private LocalDate scheduleSeminar() { project.setFinalSeminarRuleExempted(true); // to bypass rough draft approval FinalSeminarDetails details = new FinalSeminarDetails("Zoom", false, 1, 1, Language.SWEDISH, Language.ENGLISH, "zoom id 123"); diff --git a/view/src/main/java/se/su/dsv/scipro/crosscutting/NotifyFailedReflection.java b/view/src/main/java/se/su/dsv/scipro/crosscutting/NotifyFailedReflection.java new file mode 100644 index 0000000000..867703dde2 --- /dev/null +++ b/view/src/main/java/se/su/dsv/scipro/crosscutting/NotifyFailedReflection.java @@ -0,0 +1,46 @@ +package se.su.dsv.scipro.crosscutting; + +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; +import jakarta.inject.Inject; +import se.su.dsv.scipro.data.dataobjects.Member; +import se.su.dsv.scipro.notifications.NotificationController; +import se.su.dsv.scipro.notifications.dataobject.NotificationSource; +import se.su.dsv.scipro.notifications.dataobject.ProjectEvent; +import se.su.dsv.scipro.reflection.ReflectionImprovementsRequestedEvent; +import se.su.dsv.scipro.reflection.ReflectionImprovementsSubmittedEvent; + +import java.util.Set; + +public class NotifyFailedReflection { + private final NotificationController notificationController; + + @Inject + public NotifyFailedReflection(NotificationController notificationController, EventBus eventBus) { + this.notificationController = notificationController; + eventBus.register(this); + } + + @Subscribe + public void reflectionImprovementsRequested(ReflectionImprovementsRequestedEvent event) { + NotificationSource source = new NotificationSource(); + source.setMessage(event.supervisorComment()); + notificationController.notifyCustomProject( + event.project(), + ProjectEvent.Event.REFLECTION_IMPROVEMENTS_REQUESTED, + source, + Set.of(new Member(event.author(), Member.Type.AUTHOR))); + } + + @Subscribe + public void reflectionImprovementsSubmittted(ReflectionImprovementsSubmittedEvent event) { + NotificationSource source = new NotificationSource(); + source.setMessage(event.reflection()); + source.setAdditionalMessage(event.author().getFullName()); + notificationController.notifyCustomProject( + event.project(), + ProjectEvent.Event.REFLECTION_IMPROVEMENTS_SUBMITTED, + source, + Set.of(new Member(event.project().getHeadSupervisor(), Member.Type.SUPERVISOR))); + } +} diff --git a/view/src/main/java/se/su/dsv/scipro/grading/CriteriaPanel.html b/view/src/main/java/se/su/dsv/scipro/grading/CriteriaPanel.html index 079fb7b067..8794749252 100644 --- a/view/src/main/java/se/su/dsv/scipro/grading/CriteriaPanel.html +++ b/view/src/main/java/se/su/dsv/scipro/grading/CriteriaPanel.html @@ -49,10 +49,16 @@ </div> </wicket:fragment> </div> - <wicket:container wicket:id="reflection"> + <div wicket:id="reflection"> + <wicket:enclosure> + <div class="alert alert-danger"> + <h4 class="alert-heading">Improvements requested</h4> + <wicket:container wicket:id="improvementsNeeded"/> + </div> + </wicket:enclosure> <a wicket:id="showReflection" href="#">View reflection</a> <div wicket:id="modal"></div> - </wicket:container> + </div> </fieldset> </wicket:panel> </body> diff --git a/view/src/main/java/se/su/dsv/scipro/grading/CriteriaPanel.java b/view/src/main/java/se/su/dsv/scipro/grading/CriteriaPanel.java index e5475c42ed..011cb74f9f 100644 --- a/view/src/main/java/se/su/dsv/scipro/grading/CriteriaPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/grading/CriteriaPanel.java @@ -30,10 +30,12 @@ import se.su.dsv.scipro.finalseminar.FinalSeminar; import se.su.dsv.scipro.finalseminar.FinalSeminarOpposition; import se.su.dsv.scipro.finalseminar.FinalSeminarService; import se.su.dsv.scipro.project.Project; +import se.su.dsv.scipro.reflection.Reflection; import se.su.dsv.scipro.reflection.ReflectionService; import se.su.dsv.scipro.report.AbstractGradingCriterion; import se.su.dsv.scipro.report.GradingCriterion; import se.su.dsv.scipro.report.GradingCriterionPoint; +import se.su.dsv.scipro.report.GradingReport; import se.su.dsv.scipro.report.SupervisorGradingReport; import se.su.dsv.scipro.system.Language; import se.su.dsv.scipro.system.User; @@ -264,14 +266,33 @@ public class CriteriaPanel extends GenericPanel<SupervisorGradingReport> { super(id, author); this.gradingCriterion = gradingCriterion; - IModel<String> reflection = LoadableDetachableModel.of(() -> { + IModel<Reflection> reflection = LoadableDetachableModel.of(() -> { Project project = CriteriaPanel.this.getModelObject().getProject(); - return reflectionService.getSubmittedReflection(project, author.getObject()); + return reflectionService.getReflection(project, author.getObject()); + }); + IModel<String> improvementsNeeded = reflection + .as(Reflection.ImprovementsNeeded.class) + .map(Reflection.ImprovementsNeeded::commentBySupervisor); + + add(new MultiLineLabel("improvementsNeeded", improvementsNeeded) { + @Override + protected void onConfigure() { + super.onConfigure(); + setVisible(!getDefaultModelObjectAsString().isBlank()); + } }); modal = new LargeModalWindow("modal"); modal.setTitle("Reflection"); - modal.setContent(id_ -> new MultiLineLabel(id_, new NullReplacementModel(reflection, "No reflection filled in."))); + modal.setContent(modalBodyId -> { + IModel<Project> projectModel = CriteriaPanel.this.getModel().map(GradingReport::getProject); + return new ReflectionModalBodyPanel(modalBodyId, projectModel, author); + }); + this.setOutputMarkupId(true); + this.setOutputMarkupPlaceholderTag(true); + modal.onClose(target -> { + target.add(ReflectionFeedbackPanel.this); + }); add(modal); WebMarkupContainer showReflection = new WebMarkupContainer("showReflection") { diff --git a/view/src/main/java/se/su/dsv/scipro/grading/ReflectionModalBodyPanel.html b/view/src/main/java/se/su/dsv/scipro/grading/ReflectionModalBodyPanel.html new file mode 100644 index 0000000000..7840492505 --- /dev/null +++ b/view/src/main/java/se/su/dsv/scipro/grading/ReflectionModalBodyPanel.html @@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="UTF-8"?> +<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org"> +<body> +<wicket:panel> + <wicket:enclosure> + <div class="alert alert-info"> + <h4 class="alert-heading"> + <wicket:message key="improvements_requested"> + You've requested improvements to the submitted version. + </wicket:message> + </h4> + <wicket:container wicket:id="improvements_needed_supervisor_feedback"> + [Supervisor feedback on needed improvements] + </wicket:container> + </div> + </wicket:enclosure> + + <wicket:container wicket:id="reflection_text"> + [Authors submitted reflection] + </wicket:container> + + <button class="btn btn-outline-secondary" wicket:id="show_edit_reflection_form"> + <wicket:message key="edit_reflection"> + Edit reflection + </wicket:message> + </button> + <button class="btn btn-outline-secondary" wicket:id="show_request_improvements_form"> + <wicket:message key="request_improvements"> + Request improvements + </wicket:message> + </button> + + <form wicket:id="request_improvements_form"> + <hr> + <p> + <wicket:message key="request_improvements_text"> + Please provide feedback on what improvements are needed in the submitted version. + </wicket:message> + </p> + <div class="mb-3"> + <label class="form-label" wicket:for="comment"> + <wicket:message key="comment"> + Comment + </wicket:message> + </label> + <textarea class="form-control" wicket:id="comment" rows="5"></textarea> + </div> + <button class="btn btn-primary" wicket:id="submit"> + <wicket:message key="request_improvements"> + Request improvements + </wicket:message> + </button> + <button class="btn btn-link" wicket:id="cancel"> + <wicket:message key="cancel"> + Cancel + </wicket:message> + </button> + </form> + + <form wicket:id="edit_reflection_form"> + <div class="mb-3"> + <label class="form-label"> + <wicket:message key="reflection"> + Reflection + </wicket:message> + </label> + <textarea class="form-control" wicket:id="reflection" rows="10"></textarea> + </div> + <button class="btn btn-primary" wicket:id="submit"> + <wicket:message key="save"> + Save + </wicket:message> + </button> + <button class="btn btn-link" wicket:id="cancel"> + <wicket:message key="cancel"> + Cancel + </wicket:message> + </button> + </form> +</wicket:panel> +</body> +</html> \ No newline at end of file diff --git a/view/src/main/java/se/su/dsv/scipro/grading/ReflectionModalBodyPanel.java b/view/src/main/java/se/su/dsv/scipro/grading/ReflectionModalBodyPanel.java new file mode 100644 index 0000000000..895e65018f --- /dev/null +++ b/view/src/main/java/se/su/dsv/scipro/grading/ReflectionModalBodyPanel.java @@ -0,0 +1,191 @@ +package se.su.dsv.scipro.grading; + +import jakarta.inject.Inject; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.AjaxLink; +import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink; +import org.apache.wicket.markup.html.basic.MultiLineLabel; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.form.TextArea; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import se.su.dsv.scipro.project.Project; +import se.su.dsv.scipro.reflection.Reflection; +import se.su.dsv.scipro.reflection.ReflectionService; +import se.su.dsv.scipro.system.User; + +/** + * This is not meant to be a re-usable panel and is made specifically to be used + * as the body of the modal dialog that opens when a supervisor views the + * author's reflection as they're doing their final individual assessment. + */ +class ReflectionModalBodyPanel extends Panel { + @Inject + private ReflectionService reflectionService; + + private final IModel<Project> projectModel; + private final IModel<User> authorModel; + + private enum State { VIEWING, REQUESTING_IMPROVEMENTS, EDITING } + + private State state = State.VIEWING; + + ReflectionModalBodyPanel(String id, IModel<Project> projectModel, IModel<User> authorModel) { + super(id); + this.projectModel = projectModel; + this.authorModel = authorModel; + + setOutputMarkupPlaceholderTag(true); // enable ajax refreshing of the entire body + + IModel<Reflection> reflectionModel = projectModel.combineWith(authorModel, reflectionService::getReflection); + + add(new MultiLineLabel("reflection_text", reflectionModel.map(this::getReflectionText)) { + @Override + protected void onConfigure() { + super.onConfigure(); + setVisible(state != State.EDITING); + } + }); + + add(new MultiLineLabel("improvements_needed_supervisor_feedback", reflectionModel + .as(Reflection.ImprovementsNeeded.class) + .map(Reflection.ImprovementsNeeded::commentBySupervisor)) { + @Override + protected void onConfigure() { + super.onConfigure(); + setVisible(!getDefaultModelObjectAsString().isBlank()); + } + }); + + add(new RequestImprovementsForm("request_improvements_form", reflectionModel)); + add(new SupervisorEditReflectionForm("edit_reflection_form", reflectionModel)); + + add(new AjaxLink<>("show_request_improvements_form", reflectionModel) { + @Override + public void onClick(AjaxRequestTarget target) { + ReflectionModalBodyPanel.this.state = State.REQUESTING_IMPROVEMENTS; + target.add(ReflectionModalBodyPanel.this); + } + + @Override + protected void onConfigure() { + super.onConfigure(); + Reflection reflection = getModelObject(); + boolean canRequestImprovements = reflection instanceof Reflection.Submitted; + setVisible(state == State.VIEWING && canRequestImprovements && isEnabledInHierarchy()); + } + }); + + add(new AjaxLink<>("show_edit_reflection_form", reflectionModel) { + @Override + public void onClick(AjaxRequestTarget target) { + ReflectionModalBodyPanel.this.state = State.EDITING; + target.add(ReflectionModalBodyPanel.this); + } + + @Override + protected void onConfigure() { + super.onConfigure(); + Reflection reflection = getModelObject(); + boolean canEditReflection = reflection instanceof Reflection.Submitted || reflection instanceof Reflection.ImprovementsNeeded; + setVisible(state == State.VIEWING && canEditReflection && isEnabledInHierarchy()); + } + }); + } + + private String getReflectionText(Reflection reflection) { + if (reflection instanceof Reflection.Submitted submitted) { + return submitted.reflection(); + } else if (reflection instanceof Reflection.ImprovementsNeeded improvementsNeeded) { + return improvementsNeeded.oldReflection(); + } else { + return getString("reflection_not_submitted"); + } + } + + @Override + protected void onDetach() { + this.projectModel.detach(); + this.authorModel.detach(); + super.onDetach(); + } + + private class RequestImprovementsForm extends Form<Reflection> { + public RequestImprovementsForm(String id, IModel<Reflection> reflectionModel) { + super(id, reflectionModel); + + IModel<String> commentModel = new Model<>(); + + TextArea<String> comment = new TextArea<>("comment", commentModel); + comment.setRequired(true); + add(comment); + + add(new AjaxSubmitLink("submit") { + @Override + protected void onSubmit(AjaxRequestTarget target) { + super.onSubmit(target); + + reflectionService.requestNewReflection( + projectModel.getObject(), + authorModel.getObject(), + commentModel.getObject()); + + ReflectionModalBodyPanel.this.state = State.VIEWING; + target.add(ReflectionModalBodyPanel.this); + } + }); + add(new AjaxLink<>("cancel") { + @Override + public void onClick(AjaxRequestTarget target) { + ReflectionModalBodyPanel.this.state = State.VIEWING; + target.add(ReflectionModalBodyPanel.this); + } + }); + } + + @Override + protected void onConfigure() { + super.onConfigure(); + setVisible(state == State.REQUESTING_IMPROVEMENTS && getModelObject() instanceof Reflection.Submitted); + } + } + + private class SupervisorEditReflectionForm extends Form<Reflection> { + public SupervisorEditReflectionForm(String id, IModel<Reflection> reflectionModel) { + super(id, reflectionModel); + + IModel<String> reflectionTextModel = new Model<>(getReflectionText(reflectionModel.getObject())); + + TextArea<String> reflectionTextArea = new TextArea<>("reflection", reflectionTextModel); + reflectionTextArea.setRequired(true); + add(reflectionTextArea); + + add(new AjaxSubmitLink("submit") { + @Override + protected void onSubmit(AjaxRequestTarget target) { + reflectionService.submitReflection( + projectModel.getObject(), + authorModel.getObject(), + reflectionTextModel.getObject()); + + ReflectionModalBodyPanel.this.state = State.VIEWING; + target.add(ReflectionModalBodyPanel.this); + } + }); + add(new AjaxLink<>("cancel") { + @Override + public void onClick(AjaxRequestTarget target) { + ReflectionModalBodyPanel.this.state = State.VIEWING; + target.add(ReflectionModalBodyPanel.this); + } + }); + } + + @Override + protected void onConfigure() { + super.onConfigure(); + setVisible(state == State.EDITING); + } + } +} diff --git a/view/src/main/java/se/su/dsv/scipro/grading/ReflectionModalBodyPanel.utf8.properties b/view/src/main/java/se/su/dsv/scipro/grading/ReflectionModalBodyPanel.utf8.properties new file mode 100644 index 0000000000..cf818f1e92 --- /dev/null +++ b/view/src/main/java/se/su/dsv/scipro/grading/ReflectionModalBodyPanel.utf8.properties @@ -0,0 +1,10 @@ +improvements_requested=You've requested improvements to the submitted version. +request_improvements=Request improvements +comment=Comment +reflection_not_submitted=Reflection not submitted yet +request_improvements_text=If the submitted reflection does not meet the minimum requirements \ + you can request improvements from the student. The student will be notified and can submit a new reflection. \ + Use the comment field to provide feedback to the student. +edit_reflection=Edit reflection +reflection=Reflection +cancel=Cancel diff --git a/view/src/main/java/se/su/dsv/scipro/notifications/pages/NotificationLandingPage.java b/view/src/main/java/se/su/dsv/scipro/notifications/pages/NotificationLandingPage.java index b3b73a4bec..0fc12af49a 100644 --- a/view/src/main/java/se/su/dsv/scipro/notifications/pages/NotificationLandingPage.java +++ b/view/src/main/java/se/su/dsv/scipro/notifications/pages/NotificationLandingPage.java @@ -158,7 +158,7 @@ public class NotificationLandingPage extends WebPage { setResponsePage(RoughDraftApprovalDecisionPage.class, reviewerParameters); } break; - case REVIEWER_GRADING_INITIAL_ASSESSMENT_DONE, REVIEWER_GRADING_REPORT_SUBMITTED: + case REVIEWER_GRADING_INITIAL_ASSESSMENT_DONE, REVIEWER_GRADING_REPORT_SUBMITTED, REFLECTION_IMPROVEMENTS_SUBMITTED: if (project.isSupervisor(currentUser)) { setResponsePage(SupervisorGradingReportPage.class, pp); } diff --git a/view/src/main/java/se/su/dsv/scipro/project/panels/FinalStepsPanel.html b/view/src/main/java/se/su/dsv/scipro/project/panels/FinalStepsPanel.html index a50d6d7828..6cc7d5661d 100644 --- a/view/src/main/java/se/su/dsv/scipro/project/panels/FinalStepsPanel.html +++ b/view/src/main/java/se/su/dsv/scipro/project/panels/FinalStepsPanel.html @@ -38,6 +38,30 @@ <div wicket:id="current_thesis_file"></div> </div> </wicket:enclosure> + <wicket:enclosure child="old_reflection"> + <div class="alert alert-info"> + <h4 class="alert-heading"> + <wicket:message key="reflection_improvements_needed_heading"> + Reflection improvements needed + </wicket:message> + </h4> + <p> + <wicket:message key="reflection_improvements_needed"> + Your supervisor has requested that you improve and resubmit your reflection. + See their comments below about what changes are necessary. + </wicket:message> + </p> + <p wicket:id="supervisor_comment"> + [You need to reflect more on the methods you used.] + </p> + </div> + <h4> + <wicket:message key="old_reflection"> + Your previous reflection + </wicket:message> + </h4> + <p wicket:id="old_reflection"></p> + </wicket:enclosure> <div class="mb-3"> <label class="form-label" wicket:for="reflection"> <wicket:message key="reflection">[Reflection]</wicket:message> diff --git a/view/src/main/java/se/su/dsv/scipro/project/panels/FinalStepsPanel.java b/view/src/main/java/se/su/dsv/scipro/project/panels/FinalStepsPanel.java index 0283f15c13..95d9fb319a 100644 --- a/view/src/main/java/se/su/dsv/scipro/project/panels/FinalStepsPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/project/panels/FinalStepsPanel.java @@ -24,6 +24,7 @@ import se.su.dsv.scipro.grading.PublicationMetadata; import se.su.dsv.scipro.grading.PublicationMetadataFormComponentPanel; import se.su.dsv.scipro.grading.PublicationMetadataService; import se.su.dsv.scipro.project.Project; +import se.su.dsv.scipro.reflection.Reflection; import se.su.dsv.scipro.reflection.ReflectionService; import se.su.dsv.scipro.session.SciProSession; @@ -45,17 +46,20 @@ public class FinalStepsPanel extends GenericPanel<Project> { add(new FencedFeedbackPanel("feedback", this)); - IModel<String> reflection = LoadableDetachableModel.of(() -> - reflectionService.getSubmittedReflection(projectModel.getObject(), SciProSession.get().getUser())); - add(new MultiLineLabel("reflection", reflection) { + IModel<Reflection> currentReflection = LoadableDetachableModel.of(() -> + reflectionService.getReflection(projectModel.getObject(), SciProSession.get().getUser())); + IModel<String> reflectionText = currentReflection + .as(Reflection.Submitted.class) + .map(Reflection.Submitted::reflection); + add(new MultiLineLabel("reflection", reflectionText) { @Override protected void onConfigure() { super.onConfigure(); - setVisible(getDefaultModelObject() != null); + setVisible(!getDefaultModelObjectAsString().isBlank()); } }); - add(new FinalStepsForm("submit_reflection", projectModel)); + add(new FinalStepsForm("submit_reflection", projectModel, currentReflection)); } @Override @@ -67,22 +71,49 @@ public class FinalStepsPanel extends GenericPanel<Project> { private class FinalStepsForm extends Form<Project> { private final FinalThesisUploadComponent thesisFileUpload; private final IModel<PublicationMetadata> publicationMetadataModel; + private final IModel<Reflection> currentReflection; private IModel<String> reflectionModel; private IModel<PublishingConsentService.Level> levelModel; - public FinalStepsForm(String id, IModel<Project> projectModel) { + public FinalStepsForm(String id, IModel<Project> projectModel, IModel<Reflection> currentReflection) { super(id, projectModel); + this.currentReflection = currentReflection; + + IModel<Reflection.ImprovementsNeeded> improvementsNeeded = this.currentReflection.as(Reflection.ImprovementsNeeded.class); + + IModel<String> oldReflection = improvementsNeeded.map(Reflection.ImprovementsNeeded::oldReflection); + add(new MultiLineLabel("old_reflection", oldReflection) { + @Override + protected void onConfigure() { + super.onConfigure(); + setVisibilityAllowed(!getDefaultModelObjectAsString().isBlank()); + } + }); + + add(new MultiLineLabel("supervisor_comment", improvementsNeeded.map(Reflection.ImprovementsNeeded::commentBySupervisor)) { + @Override + protected void onConfigure() { + super.onConfigure(); + setVisibilityAllowed(!getDefaultModelObjectAsString().isBlank()); + } + }); reflectionModel = new Model<>(); - TextArea<String> reflectionTextArea = new TextArea<>("reflection", reflectionModel); + TextArea<String> reflectionTextArea = new TextArea<>("reflection", reflectionModel) { + @Override + protected void onConfigure() { + super.onConfigure(); + setVisible(FinalStepsForm.this.currentReflection.getObject().isSubmittable()); + } + }; reflectionTextArea.setRequired(true); add(reflectionTextArea); IModel<PublishingConsentService.PublishingConsent> publishingConsent = LoadableDetachableModel.of(() -> publishingConsentService.getPublishingConsent(getModelObject(), SciProSession.get().getUser())); - levelModel = new Model<>(); + levelModel = new Model<>(publishingConsent.getObject().selected()); FormComponent<PublishingConsentService.Level> publishingConsentLevel = new BootstrapRadioChoice<>( "publishingConsentLevel", levelModel, @@ -111,7 +142,13 @@ public class FinalStepsPanel extends GenericPanel<Project> { currentThesisFile.add(new OppositeVisibility(thesisFileUpload)); add(currentThesisFile); publicationMetadataModel = LoadableDetachableModel.of(() -> publicationMetadataService.getByProject(getModelObject())); - WebMarkupContainer publicationMetadata = new WebMarkupContainer("publication_metadata"); + WebMarkupContainer publicationMetadata = new WebMarkupContainer("publication_metadata") { + @Override + protected void onConfigure() { + super.onConfigure(); + setEnabled(finalThesisService.isUploadAllowed(FinalStepsPanel.FinalStepsForm.this.getModelObject())); + } + }; add(publicationMetadata); publicationMetadata.add(new PublicationMetadataFormComponentPanel("publication_metadata_components", publicationMetadataModel)); } @@ -119,7 +156,7 @@ public class FinalStepsPanel extends GenericPanel<Project> { @Override protected void onConfigure() { super.onConfigure(); - setVisibilityAllowed(reflectionService.hasToFillInReflection(getModelObject(), SciProSession.get().getUser())); + setVisibilityAllowed(currentReflection.getObject().isSubmittable()); } @Override @@ -131,6 +168,7 @@ public class FinalStepsPanel extends GenericPanel<Project> { new WicketProjectFileUpload(finalThesisUpload.fileUpload(), FinalStepsPanel.this.getModelObject()), finalThesisUpload.englishTitle(), finalThesisUpload.swedishTitle()); + success(getString("final_thesis_uploaded")); } reflectionService.submitReflection(getModelObject(), SciProSession.get().getUser(), reflectionModel.getObject()); if (levelModel.getObject() != null) { diff --git a/view/src/main/java/se/su/dsv/scipro/project/panels/FinalStepsPanel.utf8.properties b/view/src/main/java/se/su/dsv/scipro/project/panels/FinalStepsPanel.utf8.properties index a0f79eb71a..f21ad3bd37 100644 --- a/view/src/main/java/se/su/dsv/scipro/project/panels/FinalStepsPanel.utf8.properties +++ b/view/src/main/java/se/su/dsv/scipro/project/panels/FinalStepsPanel.utf8.properties @@ -9,3 +9,8 @@ current_final_thesis=Final thesis publication_metadata_why=Please provide the following metadata. englishTitle=English title swedishTitle=Swedish title +reflection_improvements_needed_heading=Reflection improvements needed +reflection_improvements_needed=Your supervisor has requested that you improve and resubmit your reflection. \ +See their comments below about what changes are necessary. +old_reflection=Your previous reflection +final_thesis_uploaded=Final thesis uploaded diff --git a/view/src/main/java/se/su/dsv/scipro/wicket-package.utf8.properties b/view/src/main/java/se/su/dsv/scipro/wicket-package.utf8.properties index 74aa56c867..97ea5d57c3 100644 --- a/view/src/main/java/se/su/dsv/scipro/wicket-package.utf8.properties +++ b/view/src/main/java/se/su/dsv/scipro/wicket-package.utf8.properties @@ -65,6 +65,8 @@ ProjectEvent.FIRST_MEETING = First meeting created. (with date, time, place/room ProjectEvent.OPPOSITION_FAILED = An author fails their opposition. ProjectEvent.PARTICIPATION_APPROVED = An author's active participation is approved. ProjectEvent.PARTICIPATION_FAILED = An author fails their active participation. +ProjectEvent.REFLECTION_IMPROVEMENTS_REQUESTED = Reflection improvements requested. +ProjectEvent.REFLECTION_IMPROVEMENTS_SUBMITTED = Reflection improvements submitted. ProjectForumEvent.NEW_FORUM_POST = Forum thread created. ProjectForumEvent.NEW_FORUM_POST_COMMENT = Comment posted in forum thread. diff --git a/view/src/test/java/se/su/dsv/scipro/SciProTest.java b/view/src/test/java/se/su/dsv/scipro/SciProTest.java index e712c36790..2b469c39ec 100755 --- a/view/src/test/java/se/su/dsv/scipro/SciProTest.java +++ b/view/src/test/java/se/su/dsv/scipro/SciProTest.java @@ -139,6 +139,7 @@ import java.util.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) public abstract class SciProTest { @@ -390,6 +391,8 @@ public abstract class SciProTest { publicationMetadata.setProject(answer.getArgument(0)); return publicationMetadata; }); + lenient().when(publishingConsentService.getPublishingConsent(any(), any())) + .thenReturn(new PublishingConsentService.PublishingConsent(null, List.of())); } @BeforeEach diff --git a/war/src/main/java/se/su/dsv/scipro/war/WicketConfiguration.java b/war/src/main/java/se/su/dsv/scipro/war/WicketConfiguration.java index f31d390c16..bb255d4915 100644 --- a/war/src/main/java/se/su/dsv/scipro/war/WicketConfiguration.java +++ b/war/src/main/java/se/su/dsv/scipro/war/WicketConfiguration.java @@ -10,6 +10,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import se.su.dsv.scipro.SciProApplication; import se.su.dsv.scipro.crosscutting.ForwardPhase2Feedback; +import se.su.dsv.scipro.crosscutting.NotifyFailedReflection; import se.su.dsv.scipro.crosscutting.ReviewerAssignedNotifications; import se.su.dsv.scipro.crosscutting.ReviewerSupportMailer; import se.su.dsv.scipro.crosscutting.ReviewingNotifications; @@ -87,4 +88,13 @@ public class WicketConfiguration { return new ReviewerAssignedNotifications(roughDraftApprovalService, finalSeminarApprovalService, notificationController, eventBus); } + + // Not sure why this dependency lives in the view module + @Bean + public NotifyFailedReflection notifyFailedReflection( + EventBus eventBus, + NotificationController notificationController) + { + return new NotifyFailedReflection(notificationController, eventBus); + } }