JPA: Fix up @ManyToMany relationships.

IntelliJ does not appear to be capable of detecting many-to-many
relationships, instead generating one-to-many relationships with join
tables.  To reflect the data model more accurately, this patch changes
these into actual @ManyToMany properties.

Change-Id: Ib813e7df64b1b3d77df3e7f904d279f320029f4b
diff --git a/src/main/scala/eu/mulk/entity/Article.java b/src/main/scala/eu/mulk/entity/Article.java
index 6fc6794..8289a99 100644
--- a/src/main/scala/eu/mulk/entity/Article.java
+++ b/src/main/scala/eu/mulk/entity/Article.java
@@ -3,10 +3,13 @@
 import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
 import java.util.Collection;
 import java.util.Objects;
+import java.util.Set;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
@@ -17,7 +20,7 @@
 
   private int id;
   private Collection<ArticleAlias> aliases;
-  private Collection<ArticleCategoryMembership> categoryMemberships;
+  private Set<Category> categories;
   private Collection<ArticleRevision> revisions;
   private ArticleType type;
   private Collection<Comment> comments;
@@ -59,14 +62,17 @@
     this.aliases = aliases;
   }
 
-  @OneToMany(mappedBy = "article")
-  public Collection<ArticleCategoryMembership> getCategoryMemberships() {
-    return categoryMemberships;
+  @ManyToMany
+  @JoinTable(name = "article_category_memberships",
+      joinColumns = @JoinColumn(name = "article"),
+      inverseJoinColumns = @JoinColumn(name = "category")
+  )
+  public Set<Category> getCategories() {
+    return categories;
   }
 
-  public void setCategoryMemberships(
-      Collection<ArticleCategoryMembership> categoryMemberships) {
-    this.categoryMemberships = categoryMemberships;
+  public void setCategories(Set<Category> categories) {
+    this.categories = categories;
   }
 
   @OneToMany(mappedBy = "article")
diff --git a/src/main/scala/eu/mulk/entity/ArticleCategoryMembership.java b/src/main/scala/eu/mulk/entity/ArticleCategoryMembership.java
deleted file mode 100644
index dd5982d..0000000
--- a/src/main/scala/eu/mulk/entity/ArticleCategoryMembership.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package eu.mulk.entity;
-
-import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
-import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
-
-@Entity
-@Table(name = "article_category_memberships", schema = "public", catalog = "mulkcms")
-@IdClass(ArticleCategoryMembershipPK.class)
-public class ArticleCategoryMembership extends PanacheEntityBase {
-
-  private int articleId;
-  private String category;
-  private Article article;
-
-  @Id
-  @Column(name = "article", nullable = false)
-  public int getArticleId() {
-    return articleId;
-  }
-
-  public void setArticleId(int articleId) {
-    this.articleId = articleId;
-  }
-
-  @Id
-  @Column(name = "category", nullable = false, length = -1)
-  public String getCategory() {
-    return category;
-  }
-
-  public void setCategory(String category) {
-    this.category = category;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    ArticleCategoryMembership that = (ArticleCategoryMembership) o;
-    return articleId == that.articleId &&
-        Objects.equals(category, that.category);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(articleId, category);
-  }
-
-  @ManyToOne
-  @JoinColumn(name = "article", referencedColumnName = "id", nullable = false, insertable = false, updatable = false)
-  public Article getArticle() {
-    return article;
-  }
-
-  public void setArticle(Article article) {
-    this.article = article;
-  }
-}
diff --git a/src/main/scala/eu/mulk/entity/ArticleCategoryMembershipPK.java b/src/main/scala/eu/mulk/entity/ArticleCategoryMembershipPK.java
deleted file mode 100644
index 97ee625..0000000
--- a/src/main/scala/eu/mulk/entity/ArticleCategoryMembershipPK.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package eu.mulk.entity;
-
-import java.io.Serializable;
-import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Id;
-
-public class ArticleCategoryMembershipPK implements Serializable {
-
-  private int articleId;
-  private String category;
-
-  @Column(name = "article", nullable = false)
-  @Id
-  public int getArticleId() {
-    return articleId;
-  }
-
-  public void setArticleId(int articleId) {
-    this.articleId = articleId;
-  }
-
-  @Column(name = "category", nullable = false, length = -1)
-  @Id
-  public String getCategory() {
-    return category;
-  }
-
-  public void setCategory(String category) {
-    this.category = category;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    ArticleCategoryMembershipPK that = (ArticleCategoryMembershipPK) o;
-    return articleId == that.articleId &&
-        Objects.equals(category, that.category);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(articleId, category);
-  }
-}
diff --git a/src/main/scala/eu/mulk/entity/ArticleRevision.java b/src/main/scala/eu/mulk/entity/ArticleRevision.java
index 278c304..c0f8caf 100644
--- a/src/main/scala/eu/mulk/entity/ArticleRevision.java
+++ b/src/main/scala/eu/mulk/entity/ArticleRevision.java
@@ -4,11 +4,14 @@
 import java.sql.Timestamp;
 import java.util.Collection;
 import java.util.Objects;
+import java.util.Set;
 import javax.persistence.Basic;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
@@ -25,8 +28,8 @@
   private String status;
   private String globalId;
   private Collection<ArticleRevisionCharacteristic> characteristics;
-  private Collection<ArticleRevisionParenthood> children;
-  private Collection<ArticleRevisionParenthood> parents;
+  private Set<ArticleRevision> children;
+  private Set<ArticleRevision> parents;
   private Article article;
   private User authors;
 
@@ -133,21 +136,25 @@
     this.characteristics = characteristics;
   }
 
-  @OneToMany(mappedBy = "parent")
-  public Collection<ArticleRevisionParenthood> getChildren() {
+  @ManyToMany
+  @JoinTable(name = "article_revision_parenthood",
+      joinColumns = @JoinColumn(name = "parent"),
+      inverseJoinColumns = @JoinColumn(name = "child")
+  )
+  public Set<ArticleRevision> getChildren() {
     return children;
   }
 
-  public void setChildren(Collection<ArticleRevisionParenthood> children) {
+  public void setChildren(Set<ArticleRevision> children) {
     this.children = children;
   }
 
-  @OneToMany(mappedBy = "child")
-  public Collection<ArticleRevisionParenthood> getParents() {
+  @ManyToMany(mappedBy = "children")
+  public Set<ArticleRevision> getParents() {
     return parents;
   }
 
-  public void setParents(Collection<ArticleRevisionParenthood> parents) {
+  public void setParents(Set<ArticleRevision> parents) {
     this.parents = parents;
   }
 
diff --git a/src/main/scala/eu/mulk/entity/ArticleRevisionParenthood.java b/src/main/scala/eu/mulk/entity/ArticleRevisionParenthood.java
deleted file mode 100644
index 823ca09..0000000
--- a/src/main/scala/eu/mulk/entity/ArticleRevisionParenthood.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package eu.mulk.entity;
-
-import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
-import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
-
-@Entity
-@Table(name = "article_revision_parenthood", schema = "public", catalog = "mulkcms")
-@IdClass(ArticleRevisionParenthoodPK.class)
-public class ArticleRevisionParenthood extends PanacheEntityBase {
-
-  private int parentId;
-  private int childId;
-  private ArticleRevision parent;
-  private ArticleRevision child;
-
-  @Id
-  @Column(name = "parent", nullable = false)
-  public int getParentId() {
-    return parentId;
-  }
-
-  public void setParentId(int parentId) {
-    this.parentId = parentId;
-  }
-
-  @Id
-  @Column(name = "child", nullable = false)
-  public int getChildId() {
-    return childId;
-  }
-
-  public void setChildId(int childId) {
-    this.childId = childId;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    ArticleRevisionParenthood that = (ArticleRevisionParenthood) o;
-    return parentId == that.parentId &&
-        childId == that.childId;
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(parentId, childId);
-  }
-
-  @ManyToOne
-  @JoinColumn(name = "parent", referencedColumnName = "id", nullable = false, insertable = false, updatable = false)
-  public ArticleRevision getParent() {
-    return parent;
-  }
-
-  public void setParent(ArticleRevision parent) {
-    this.parent = parent;
-  }
-
-  @ManyToOne
-  @JoinColumn(name = "child", referencedColumnName = "id", nullable = false, insertable = false, updatable = false)
-  public ArticleRevision getChild() {
-    return child;
-  }
-
-  public void setChild(ArticleRevision child) {
-    this.child = child;
-  }
-}
diff --git a/src/main/scala/eu/mulk/entity/ArticleRevisionParenthoodPK.java b/src/main/scala/eu/mulk/entity/ArticleRevisionParenthoodPK.java
deleted file mode 100644
index ecb918c..0000000
--- a/src/main/scala/eu/mulk/entity/ArticleRevisionParenthoodPK.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package eu.mulk.entity;
-
-import java.io.Serializable;
-import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Id;
-
-public class ArticleRevisionParenthoodPK implements Serializable {
-
-  private int parentId;
-  private int childId;
-
-  @Column(name = "parent", nullable = false)
-  @Id
-  public int getParentId() {
-    return parentId;
-  }
-
-  public void setParentId(int parentId) {
-    this.parentId = parentId;
-  }
-
-  @Column(name = "child", nullable = false)
-  @Id
-  public int getChildId() {
-    return childId;
-  }
-
-  public void setChildId(int childId) {
-    this.childId = childId;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    ArticleRevisionParenthoodPK that = (ArticleRevisionParenthoodPK) o;
-    return parentId == that.parentId &&
-        childId == that.childId;
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(parentId, childId);
-  }
-}
diff --git a/src/main/scala/eu/mulk/entity/Category.java b/src/main/scala/eu/mulk/entity/Category.java
index d74ccfb..44136be 100644
--- a/src/main/scala/eu/mulk/entity/Category.java
+++ b/src/main/scala/eu/mulk/entity/Category.java
@@ -3,10 +3,14 @@
 import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
 import java.util.Collection;
 import java.util.Objects;
+import java.util.Set;
 import javax.persistence.Basic;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
 
@@ -16,8 +20,8 @@
 
   private int id;
   private String name;
-  private Collection<CategoryInclusion> supercategories;
-  private Collection<CategoryInclusion> subcategories;
+  private Set<Category> supercategories;
+  private Set<Category> subcategories;
 
   @Id
   @Column(name = "id", nullable = false)
@@ -57,21 +61,25 @@
     return Objects.hash(id, name);
   }
 
-  @OneToMany(mappedBy = "subcategory")
-  public Collection<CategoryInclusion> getSupercategories() {
+  @ManyToMany
+  @JoinTable(name = "category_inclusions",
+      joinColumns = @JoinColumn(name = "category"),
+      inverseJoinColumns = @JoinColumn(name = "supercategory")
+  )
+  public Set<Category> getSupercategories() {
     return supercategories;
   }
 
-  public void setSupercategories(Collection<CategoryInclusion> supercategories) {
+  public void setSupercategories(Set<Category> supercategories) {
     this.supercategories = supercategories;
   }
 
-  @OneToMany(mappedBy = "supercategory")
-  public Collection<CategoryInclusion> getSubcategories() {
+  @ManyToMany(mappedBy = "supercategories")
+  public Set<Category> getSubcategories() {
     return subcategories;
   }
 
-  public void setSubcategories(Collection<CategoryInclusion> subcategories) {
+  public void setSubcategories(Set<Category> subcategories) {
     this.subcategories = subcategories;
   }
 }
diff --git a/src/main/scala/eu/mulk/entity/CategoryInclusion.java b/src/main/scala/eu/mulk/entity/CategoryInclusion.java
deleted file mode 100644
index 387615f..0000000
--- a/src/main/scala/eu/mulk/entity/CategoryInclusion.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package eu.mulk.entity;
-
-import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
-import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
-
-@Entity
-@Table(name = "category_inclusions", schema = "public", catalog = "mulkcms")
-@IdClass(CategoryInclusionPK.class)
-public class CategoryInclusion extends PanacheEntityBase {
-
-  private int subcategoryId;
-  private int supercategoryId;
-  private Category subcategory;
-  private Category supercategory;
-
-  @Id
-  @Column(name = "category", nullable = false)
-  public int getSubcategoryId() {
-    return subcategoryId;
-  }
-
-  public void setSubcategoryId(int subcategoryId) {
-    this.subcategoryId = subcategoryId;
-  }
-
-  @Id
-  @Column(name = "supercategory", nullable = false)
-  public int getSupercategoryId() {
-    return supercategoryId;
-  }
-
-  public void setSupercategoryId(int supercategoryId) {
-    this.supercategoryId = supercategoryId;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    CategoryInclusion that = (CategoryInclusion) o;
-    return subcategoryId == that.subcategoryId &&
-        supercategoryId == that.supercategoryId;
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(subcategoryId, supercategoryId);
-  }
-
-  @ManyToOne
-  @JoinColumn(name = "category", referencedColumnName = "id", nullable = false, insertable = false, updatable = false)
-  public Category getSubcategory() {
-    return subcategory;
-  }
-
-  public void setSubcategory(Category subcategory) {
-    this.subcategory = subcategory;
-  }
-
-  @ManyToOne
-  @JoinColumn(name = "supercategory", referencedColumnName = "id", nullable = false, insertable = false, updatable = false)
-  public Category getSupercategory() {
-    return supercategory;
-  }
-
-  public void setSupercategory(Category supercategory) {
-    this.supercategory = supercategory;
-  }
-}
diff --git a/src/main/scala/eu/mulk/entity/CategoryInclusionPK.java b/src/main/scala/eu/mulk/entity/CategoryInclusionPK.java
deleted file mode 100644
index 6ca2e03..0000000
--- a/src/main/scala/eu/mulk/entity/CategoryInclusionPK.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package eu.mulk.entity;
-
-import java.io.Serializable;
-import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Id;
-
-public class CategoryInclusionPK implements Serializable {
-
-  private int subcategoryId;
-  private int supercategoryId;
-
-  @Column(name = "category", nullable = false)
-  @Id
-  public int getSubcategoryId() {
-    return subcategoryId;
-  }
-
-  public void setSubcategoryId(int subcategoryId) {
-    this.subcategoryId = subcategoryId;
-  }
-
-  @Column(name = "supercategory", nullable = false)
-  @Id
-  public int getSupercategoryId() {
-    return supercategoryId;
-  }
-
-  public void setSupercategoryId(int supercategoryId) {
-    this.supercategoryId = supercategoryId;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    CategoryInclusionPK that = (CategoryInclusionPK) o;
-    return subcategoryId == that.subcategoryId &&
-        supercategoryId == that.supercategoryId;
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(subcategoryId, supercategoryId);
-  }
-}