Add localized texts to Benki post model.

Change-Id: I123cfe2ff06f85dc14c705b21d723d1c68fd2e00
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/posts/PostText.java b/src/main/java/eu/mulk/mulkcms2/benki/posts/PostText.java
new file mode 100644
index 0000000..01753dc
--- /dev/null
+++ b/src/main/java/eu/mulk/mulkcms2/benki/posts/PostText.java
@@ -0,0 +1,61 @@
+package eu.mulk.mulkcms2.benki.posts;
+
+import javax.annotation.CheckForNull;
+import javax.json.bind.annotation.JsonbTransient;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "post_texts", schema = "benki")
+@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
+@IdClass(PostTextPK.class)
+public abstract class PostText<OwningPost extends Post<?>> {
+
+  private static final int DESCRIPTION_CACHE_VERSION = 1;
+
+  @Id
+  @Column(name = "post", nullable = false, insertable = false, updatable = false)
+  public int postId;
+
+  @Id
+  @Column(name = "language", nullable = false, length = -1)
+  public String language;
+
+  @Column(name = "cached_description_version", nullable = true)
+  @CheckForNull
+  public Integer cachedDescriptionVersion;
+
+  @Column(name = "cached_description_html", nullable = true)
+  @CheckForNull
+  public String cachedDescriptionHtml;
+
+  @ManyToOne(fetch = FetchType.LAZY, targetEntity = Post.class)
+  @JoinColumn(name = "post", referencedColumnName = "id", nullable = false)
+  @JsonbTransient
+  public OwningPost post;
+
+  @CheckForNull
+  public final String getDescriptionHtml() {
+    if (cachedDescriptionHtml != null
+        && cachedDescriptionVersion != null
+        && cachedDescriptionVersion >= DESCRIPTION_CACHE_VERSION) {
+      return cachedDescriptionHtml;
+    } else {
+      @CheckForNull var descriptionHtml = computeDescriptionHtml();
+      cachedDescriptionHtml = descriptionHtml;
+      cachedDescriptionVersion = DESCRIPTION_CACHE_VERSION;
+      return descriptionHtml;
+    }
+  }
+
+  @CheckForNull
+  protected abstract String computeDescriptionHtml();
+}