From 2d1e04799df0db8b962cadb7aa9cdc6e4bc70d4b Mon Sep 17 00:00:00 2001
From: Tom Zhao <tom.zhao@dsv.su.se>
Date: Wed, 30 Oct 2024 10:20:59 +0100
Subject: [PATCH] task/3382: Fixed thread, forum_post,
 forum_post_file_description and their related JPA-mappings

---
 .../scipro/forum/dataobjects/ForumPost.java   | 106 ++++++++-----
 .../scipro/forum/dataobjects/ForumThread.java | 144 +++++++++++-------
 .../V389__harmonize_table_attribute_name.sql  |  47 +++++-
 3 files changed, 199 insertions(+), 98 deletions(-)

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/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/resources/db/migration/V389__harmonize_table_attribute_name.sql b/core/src/main/resources/db/migration/V389__harmonize_table_attribute_name.sql
index 7de3184163..190eb48a98 100644
--- a/core/src/main/resources/db/migration/V389__harmonize_table_attribute_name.sql
+++ b/core/src/main/resources/db/migration/V389__harmonize_table_attribute_name.sql
@@ -2922,11 +2922,56 @@ alter table `project_group_project`
             on delete cascade on update cascade;
 
 /*
- * Step 22: ???
+ * 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;
 
 
 /* Useful SQL