Benki: Model join tables properly.

Change-Id: I24bfd7a65ad72330a1862cbc408d7911263b6329
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/EffectiveRoleSubrole.java b/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/EffectiveRoleSubrole.java
deleted file mode 100644
index 4166752..0000000
--- a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/EffectiveRoleSubrole.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package eu.mulk.mulkcms2.benki.accesscontrol;
-
-import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
-import java.io.Serializable;
-import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
-import org.hibernate.annotations.Immutable;
-
-@Entity
-@Immutable
-@Table(name = "effective_role_subroles", schema = "public", catalog = "benki")
-public class EffectiveRoleSubrole extends PanacheEntityBase implements Serializable {
-
-  @Id
-  @Column(name = "superrole", nullable = true)
-  public Integer superroleId;
-
-  @Id
-  @Column(name = "subrole", nullable = true)
-  public Integer subroleId;
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (!(o instanceof EffectiveRoleSubrole)) {
-      return false;
-    }
-    EffectiveRoleSubrole that = (EffectiveRoleSubrole) o;
-    return Objects.equals(superroleId, that.superroleId)
-        && Objects.equals(subroleId, that.subroleId);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(superroleId, subroleId);
-  }
-}
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/EffectiveUserRole.java b/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/EffectiveUserRole.java
deleted file mode 100644
index 6b5c3ab..0000000
--- a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/EffectiveUserRole.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package eu.mulk.mulkcms2.benki.accesscontrol;
-
-import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
-import java.io.Serializable;
-import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
-import org.hibernate.annotations.Immutable;
-
-@Entity
-@Immutable
-@Table(name = "effective_user_roles", schema = "public", catalog = "benki")
-public class EffectiveUserRole extends PanacheEntityBase implements Serializable {
-
-  @Id
-  @Column(name = "user", nullable = true)
-  public Integer userId;
-
-  @Id
-  @Column(name = "role", nullable = true)
-  public Integer roleId;
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (!(o instanceof EffectiveUserRole)) {
-      return false;
-    }
-    EffectiveUserRole that = (EffectiveUserRole) o;
-    return Objects.equals(userId, that.userId) && Objects.equals(roleId, that.roleId);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(userId, roleId);
-  }
-}
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/Role.java b/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/Role.java
index 563a2f8..131fb69 100644
--- a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/Role.java
+++ b/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/Role.java
@@ -6,10 +6,16 @@
 import eu.mulk.mulkcms2.benki.users.UserRole;
 import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
 import java.util.Collection;
+import java.util.Set;
+import javax.persistence.CollectionTable;
 import javax.persistence.Column;
+import javax.persistence.ElementCollection;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
 
@@ -27,18 +33,40 @@
   @OneToMany(mappedBy = "target", fetch = FetchType.LAZY)
   public Collection<PostTarget> targetedPosts;
 
-  @OneToMany(mappedBy = "superrole", fetch = FetchType.LAZY)
-  public Collection<RoleSubrole> subroles;
+  @ManyToMany(fetch = FetchType.LAZY)
+  @JoinTable(
+      name = "role_subroles",
+      joinColumns = @JoinColumn(name = "superrole"),
+      inverseJoinColumns = @JoinColumn(name = "subrole"))
+  public Set<Role> directSubroles;
 
-  @OneToMany(mappedBy = "subrole", fetch = FetchType.LAZY)
-  public Collection<RoleSubrole> superroles;
+  @ManyToMany(mappedBy = "directSubroles", fetch = FetchType.LAZY)
+  public Set<Role> directSuperroles;
+
+  @ManyToMany(fetch = FetchType.LAZY)
+  @JoinTable(
+      name = "effective_role_subroles",
+      joinColumns = @JoinColumn(name = "superrole"),
+      inverseJoinColumns = @JoinColumn(name = "subrole"))
+  public Set<Role> effectiveSubroles;
+
+  @ManyToMany(mappedBy = "effectiveSubroles", fetch = FetchType.LAZY)
+  public Set<Role> effectiveSuperroles;
 
   @OneToMany(mappedBy = "target", fetch = FetchType.LAZY)
   public Collection<UserDefaultTarget> usersUsedByAsDefaultTarget;
 
   @OneToMany(mappedBy = "role", fetch = FetchType.LAZY)
-  public Collection<UserRole> users;
+  public Collection<UserRole> directUsers;
 
   @OneToMany(mappedBy = "ownedRole", fetch = FetchType.LAZY)
   public Collection<User> owningUsers;
+
+  @ManyToMany(mappedBy = "effectiveRoles", fetch = FetchType.LAZY)
+  public Collection<User> effectiveUsers;
+
+  @ElementCollection(fetch = FetchType.LAZY)
+  @CollectionTable(name = "role_tags", joinColumns = @JoinColumn(name = "role"))
+  @Column(name = "tag")
+  public Set<String> tags;
 }
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/RoleSubrole.java b/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/RoleSubrole.java
deleted file mode 100644
index 10c64ea..0000000
--- a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/RoleSubrole.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package eu.mulk.mulkcms2.benki.accesscontrol;
-
-import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
-
-@Entity
-@Table(name = "role_subroles", schema = "public", catalog = "benki")
-@IdClass(RoleSubrolePK.class)
-public class RoleSubrole extends PanacheEntityBase {
-
-  @Id
-  @Column(name = "superrole", nullable = false)
-  public int superroleId;
-
-  @Id
-  @Column(name = "subrole", nullable = false)
-  public int subroleId;
-
-  @ManyToOne(fetch = FetchType.LAZY)
-  @JoinColumn(name = "superrole", referencedColumnName = "id", nullable = false)
-  public Role superrole;
-
-  @ManyToOne(fetch = FetchType.LAZY)
-  @JoinColumn(name = "subrole", referencedColumnName = "id", nullable = false)
-  public Role subrole;
-}
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/RoleSubrolePK.java b/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/RoleSubrolePK.java
deleted file mode 100644
index f74d98b..0000000
--- a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/RoleSubrolePK.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package eu.mulk.mulkcms2.benki.accesscontrol;
-
-import java.io.Serializable;
-import javax.persistence.Column;
-import javax.persistence.Id;
-
-public class RoleSubrolePK implements Serializable {
-
-  private int superroleId;
-  private int subroleId;
-
-  @Column(name = "superrole", nullable = false)
-  @Id
-  public int getSuperroleId() {
-    return superroleId;
-  }
-
-  public void setSuperroleId(int superroleId) {
-    this.superroleId = superroleId;
-  }
-
-  @Column(name = "subrole", nullable = false)
-  @Id
-  public int getSubroleId() {
-    return subroleId;
-  }
-
-  public void setSubroleId(int subroleId) {
-    this.subroleId = subroleId;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-
-    RoleSubrolePK that = (RoleSubrolePK) o;
-
-    if (superroleId != that.superroleId) {
-      return false;
-    }
-    if (subroleId != that.subroleId) {
-      return false;
-    }
-
-    return true;
-  }
-
-  @Override
-  public int hashCode() {
-    int result = superroleId;
-    result = 31 * result + subroleId;
-    return result;
-  }
-}
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/RoleTag.java b/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/RoleTag.java
deleted file mode 100644
index 5dbda68..0000000
--- a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/RoleTag.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package eu.mulk.mulkcms2.benki.accesscontrol;
-
-import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.Table;
-
-@Entity
-@Table(name = "role_tags", schema = "public", catalog = "benki")
-@IdClass(RoleTagPK.class)
-public class RoleTag extends PanacheEntityBase {
-
-  @Id
-  @Column(name = "role", nullable = false)
-  public int roleId;
-
-  @Id
-  @Column(name = "tag", nullable = false, length = -1)
-  public String tag;
-}
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/RoleTagPK.java b/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/RoleTagPK.java
deleted file mode 100644
index 5b32f81..0000000
--- a/src/main/java/eu/mulk/mulkcms2/benki/accesscontrol/RoleTagPK.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package eu.mulk.mulkcms2.benki.accesscontrol;
-
-import java.io.Serializable;
-import javax.persistence.Column;
-import javax.persistence.Id;
-
-public class RoleTagPK implements Serializable {
-
-  private int roleId;
-  private String tag;
-
-  @Column(name = "role", nullable = false)
-  @Id
-  public int getRoleId() {
-    return roleId;
-  }
-
-  public void setRoleId(int roleId) {
-    this.roleId = roleId;
-  }
-
-  @Column(name = "tag", nullable = false, length = -1)
-  @Id
-  public String getTag() {
-    return tag;
-  }
-
-  public void setTag(String tag) {
-    this.tag = tag;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-
-    RoleTagPK roleTagPK = (RoleTagPK) o;
-
-    if (roleId != roleTagPK.roleId) {
-      return false;
-    }
-    if (tag != null ? !tag.equals(roleTagPK.tag) : roleTagPK.tag != null) {
-      return false;
-    }
-
-    return true;
-  }
-
-  @Override
-  public int hashCode() {
-    int result = roleId;
-    result = 31 * result + (tag != null ? tag.hashCode() : 0);
-    return result;
-  }
-}
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/users/User.java b/src/main/java/eu/mulk/mulkcms2/benki/users/User.java
index a090690..90b3318 100644
--- a/src/main/java/eu/mulk/mulkcms2/benki/users/User.java
+++ b/src/main/java/eu/mulk/mulkcms2/benki/users/User.java
@@ -8,11 +8,13 @@
 import eu.mulk.mulkcms2.benki.wiki.WikiPageRevision;
 import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
 import java.util.Collection;
+import java.util.Set;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
 import javax.persistence.ManyToMany;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
@@ -72,7 +74,7 @@
   public Collection<UserNickname> nicknames;
 
   @OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
-  public Collection<UserRole> roles;
+  public Collection<UserRole> directRoles;
 
   @OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
   public Collection<UserRsaKey> rsaKeys;
@@ -89,4 +91,11 @@
 
   @ManyToMany(mappedBy = "visibleTo", fetch = FetchType.LAZY)
   public Collection<Post> visiblePosts;
+
+  @ManyToMany(fetch = FetchType.LAZY)
+  @JoinTable(
+      name = "effective_user_roles",
+      joinColumns = @JoinColumn(name = "user"),
+      inverseJoinColumns = @JoinColumn(name = "role"))
+  public Set<Role> effectiveRoles;
 }