KB66 Post: Add scope field.

The scope field defines whether a post is a top-level post or a
comment and is used to select posts for the main feed.

Change-Id: I44363e3e67acbecff9844730a513ddb1d554afaf
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/posts/Post.java b/src/main/java/eu/mulk/mulkcms2/benki/posts/Post.java
index 346b71f..3a16868 100644
--- a/src/main/java/eu/mulk/mulkcms2/benki/posts/Post.java
+++ b/src/main/java/eu/mulk/mulkcms2/benki/posts/Post.java
@@ -2,6 +2,7 @@
 
 import static java.util.stream.Collectors.toList;
 
+import com.vladmihalcea.hibernate.type.basic.PostgreSQLEnumType;
 import eu.mulk.mulkcms2.benki.accesscontrol.Role;
 import eu.mulk.mulkcms2.benki.bookmarks.Bookmark;
 import eu.mulk.mulkcms2.benki.lazychat.LazychatMessage;
@@ -28,6 +29,8 @@
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
 import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
@@ -48,15 +51,23 @@
 import javax.persistence.criteria.JoinType;
 import javax.persistence.criteria.Predicate;
 import org.hibernate.Session;
+import org.hibernate.annotations.Type;
+import org.hibernate.annotations.TypeDef;
 import org.jboss.logging.Logger;
 
 @Entity
 @Table(name = "posts", schema = "benki")
 @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
+@TypeDef(name = "pg_enum", typeClass = PostgreSQLEnumType.class)
 public abstract class Post<Text extends PostText<?>> extends PanacheEntityBase {
 
   private static final Logger log = Logger.getLogger(Post.class);
 
+  public enum Scope {
+    top_level,
+    comment
+  }
+
   @Id
   @SequenceGenerator(
       allocationSize = 1,
@@ -71,6 +82,11 @@
   @CheckForNull
   public OffsetDateTime date;
 
+  @Column(nullable = false)
+  @Enumerated(EnumType.STRING)
+  @Type(type = "pg_enum")
+  public Scope scope = Scope.top_level;
+
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "newsletter", referencedColumnName = "id", nullable = true)
   @CheckForNull
@@ -204,6 +220,8 @@
       conditions.add(cb.or(localizedSearches));
     }
 
+    conditions.add(cb.equal(post.get(Post_.scope), Scope.top_level));
+
     query.where(conditions.toArray(new Predicate[0]));
 
     return query;
@@ -223,6 +241,10 @@
     return text.getDescriptionHtml();
   }
 
+  public final boolean isTopLevel() {
+    return scope == Scope.top_level;
+  }
+
   public static class PostPage<T extends Post<? extends PostText>> {
     public @CheckForNull final Integer prevCursor;
     public @CheckForNull final Integer cursor;