summaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMatthias Andreas Benkard <code@mail.matthias.benkard.de>2020-08-23 21:51:00 +0200
committerMatthias Andreas Benkard <code@mail.matthias.benkard.de>2020-08-27 21:09:12 +0200
commitd5498fcec7394d2b89667832853e239d5f496e1c (patch)
tree3d9d6ee6c1c175c22026059f4b44b2d954fac6d9 /src/main/java
parente9b14f921cdaa0357aa58f4a72f930981b3042fb (diff)
Add localized texts to Benki post model.
Change-Id: I123cfe2ff06f85dc14c705b21d723d1c68fd2e00
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/eu/mulk/mulkcms2/benki/bookmarks/Bookmark.java49
-rw-r--r--src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkResource.java9
-rw-r--r--src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkText.java31
-rw-r--r--src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkTextPK.java54
-rw-r--r--src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessage.java34
-rw-r--r--src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessageText.java28
-rw-r--r--src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessageTextPK.java54
-rw-r--r--src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatResource.java7
-rw-r--r--src/main/java/eu/mulk/mulkcms2/benki/posts/Post.java89
-rw-r--r--src/main/java/eu/mulk/mulkcms2/benki/posts/PostText.java61
-rw-r--r--src/main/java/eu/mulk/mulkcms2/benki/posts/PostTextPK.java55
11 files changed, 390 insertions, 81 deletions
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/Bookmark.java b/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/Bookmark.java
index a659049..256c988 100644
--- a/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/Bookmark.java
+++ b/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/Bookmark.java
@@ -1,7 +1,6 @@
package eu.mulk.mulkcms2.benki.bookmarks;
import eu.mulk.mulkcms2.benki.posts.Post;
-import eu.mulk.mulkcms2.common.markdown.MarkdownConverter;
import java.util.Set;
import javax.annotation.CheckForNull;
import javax.persistence.CollectionTable;
@@ -11,23 +10,14 @@ import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.Table;
-import javax.persistence.Transient;
@Entity
@Table(name = "bookmarks", schema = "benki")
-public class Bookmark extends Post {
+public class Bookmark extends Post<BookmarkText> {
@Column(name = "uri", nullable = false, length = -1)
public String uri;
- @Column(name = "title", nullable = true, length = -1)
- @CheckForNull
- public String title;
-
- @Column(name = "description", nullable = true, length = -1)
- @CheckForNull
- public String description;
-
@ElementCollection(fetch = FetchType.LAZY)
@CollectionTable(
name = "bookmark_tags",
@@ -36,13 +26,10 @@ public class Bookmark extends Post {
@Column(name = "tag")
public Set<String> tags;
- @Transient
@CheckForNull
- protected String computeDescriptionHtml() {
- if (description == null) {
- return null;
- }
- return new MarkdownConverter().htmlify(description);
+ private String getDescription() {
+ var text = getText();
+ return text == null ? null : text.description;
}
@CheckForNull
@@ -54,7 +41,8 @@ public class Bookmark extends Post {
@CheckForNull
@Override
public String getTitle() {
- return title;
+ var text = getText();
+ return text == null ? null : text.title;
}
@Override
@@ -66,4 +54,29 @@ public class Bookmark extends Post {
public boolean isLazychatMessage() {
return false;
}
+
+ public void setTitle(String x) {
+ var text = getText();
+ if (text == null) {
+ text = new BookmarkText();
+ text.post = this;
+ text.language = "";
+ texts.put(text.language, text);
+ }
+
+ text.title = x;
+ }
+
+ public void setDescription(String x) {
+ var text = getText();
+ if (text == null) {
+ text = new BookmarkText();
+ text.post = this;
+ text.language = "";
+ texts.put(text.language, text);
+ }
+
+ text.description = x;
+ text.cachedDescriptionHtml = null;
+ }
}
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkResource.java b/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkResource.java
index f81ed04..bb39be9 100644
--- a/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkResource.java
+++ b/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkResource.java
@@ -66,9 +66,9 @@ public class BookmarkResource extends PostResource {
var bookmark = new Bookmark();
bookmark.uri = uri.toString();
- bookmark.title = title;
bookmark.tags = Set.of();
- bookmark.description = description;
+ bookmark.setTitle(title);
+ bookmark.setDescription(description);
bookmark.owner = user;
bookmark.date = OffsetDateTime.now();
@@ -106,10 +106,9 @@ public class BookmarkResource extends PostResource {
}
bookmark.uri = uri.toString();
- bookmark.title = title;
bookmark.tags = Set.of();
- bookmark.description = description;
- bookmark.cachedDescriptionHtml = null;
+ bookmark.setTitle(title);
+ bookmark.setDescription(description);
bookmark.owner = user;
assignPostTargets(visibility, user, bookmark);
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkText.java b/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkText.java
new file mode 100644
index 0000000..c30f3df
--- /dev/null
+++ b/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkText.java
@@ -0,0 +1,31 @@
+package eu.mulk.mulkcms2.benki.bookmarks;
+
+import eu.mulk.mulkcms2.benki.posts.PostText;
+import eu.mulk.mulkcms2.common.markdown.MarkdownConverter;
+import javax.annotation.CheckForNull;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+@Entity
+@Table(name = "bookmark_texts", schema = "benki")
+public class BookmarkText extends PostText<Bookmark> {
+
+ @Column(name = "title", nullable = true, length = -1)
+ @CheckForNull
+ public String title;
+
+ @Column(name = "description", nullable = true, length = -1)
+ @CheckForNull
+ public String description;
+
+ @Transient
+ @CheckForNull
+ protected String computeDescriptionHtml() {
+ if (description == null) {
+ return null;
+ }
+ return new MarkdownConverter().htmlify(description);
+ }
+}
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkTextPK.java b/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkTextPK.java
new file mode 100644
index 0000000..92bda99
--- /dev/null
+++ b/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkTextPK.java
@@ -0,0 +1,54 @@
+package eu.mulk.mulkcms2.benki.bookmarks;
+
+import java.io.Serializable;
+import java.util.Objects;
+import javax.persistence.Column;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+public class BookmarkTextPK implements Serializable {
+
+ @Id
+ @Column(name = "language", nullable = false, length = -1)
+ private String language;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "bookmark", referencedColumnName = "id", nullable = false)
+ private Bookmark bookmark;
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public void setLanguage(String language) {
+ this.language = language;
+ }
+
+ public Bookmark getBookmark() {
+ return bookmark;
+ }
+
+ public void setBookmark(Bookmark bookmark) {
+ this.bookmark = bookmark;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof BookmarkTextPK)) {
+ return false;
+ }
+ BookmarkTextPK that = (BookmarkTextPK) o;
+ return Objects.equals(getBookmark(), that.getBookmark())
+ && getLanguage().equals(that.getLanguage());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getBookmark(), getLanguage());
+ }
+}
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessage.java b/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessage.java
index 5cec6aa..aa5b6eb 100644
--- a/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessage.java
+++ b/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessage.java
@@ -1,11 +1,9 @@
package eu.mulk.mulkcms2.benki.lazychat;
import eu.mulk.mulkcms2.benki.posts.Post;
-import eu.mulk.mulkcms2.common.markdown.MarkdownConverter;
import java.util.Collection;
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.OneToMany;
@@ -14,14 +12,7 @@ import javax.persistence.Transient;
@Entity
@Table(name = "lazychat_messages", schema = "benki")
-public class LazychatMessage extends Post {
-
- @Column(name = "content", nullable = true, length = -1)
- @CheckForNull
- public String content;
-
- @Column(name = "format", nullable = false, length = -1)
- public String format;
+public class LazychatMessage extends Post<LazychatMessageText> {
@OneToMany(mappedBy = "referrer", fetch = FetchType.LAZY)
@JsonbTransient
@@ -46,16 +37,6 @@ public class LazychatMessage extends Post {
return null;
}
- @CheckForNull
- @Override
- @JsonbTransient
- protected String computeDescriptionHtml() {
- if (content == null) {
- return null;
- }
- return new MarkdownConverter().htmlify(content);
- }
-
@Override
public boolean isBookmark() {
return false;
@@ -65,4 +46,17 @@ public class LazychatMessage extends Post {
public boolean isLazychatMessage() {
return true;
}
+
+ public void setContent(String x) {
+ var text = getText();
+ if (text == null) {
+ text = new LazychatMessageText();
+ text.post = this;
+ text.language = "";
+ texts.put(text.language, text);
+ }
+
+ text.cachedDescriptionHtml = null;
+ text.content = x;
+ }
}
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessageText.java b/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessageText.java
new file mode 100644
index 0000000..1a60877
--- /dev/null
+++ b/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessageText.java
@@ -0,0 +1,28 @@
+package eu.mulk.mulkcms2.benki.lazychat;
+
+import eu.mulk.mulkcms2.benki.posts.PostText;
+import eu.mulk.mulkcms2.common.markdown.MarkdownConverter;
+import javax.annotation.CheckForNull;
+import javax.json.bind.annotation.JsonbTransient;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "lazychat_message_texts", schema = "benki")
+public class LazychatMessageText extends PostText<LazychatMessage> {
+
+ @Column(name = "content", nullable = true, length = -1)
+ @CheckForNull
+ public String content;
+
+ @CheckForNull
+ @Override
+ @JsonbTransient
+ protected String computeDescriptionHtml() {
+ if (content == null) {
+ return null;
+ }
+ return new MarkdownConverter().htmlify(content);
+ }
+}
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessageTextPK.java b/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessageTextPK.java
new file mode 100644
index 0000000..33063b1
--- /dev/null
+++ b/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessageTextPK.java
@@ -0,0 +1,54 @@
+package eu.mulk.mulkcms2.benki.lazychat;
+
+import java.io.Serializable;
+import java.util.Objects;
+import javax.persistence.Column;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+public class LazychatMessageTextPK implements Serializable {
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "lazychat_message", referencedColumnName = "id", nullable = false)
+ public LazychatMessage lazychatMessage;
+
+ @Id
+ @Column(name = "language", nullable = false, length = -1)
+ private String language;
+
+ public LazychatMessage getLazychatMessage() {
+ return lazychatMessage;
+ }
+
+ public void setLazychatMessageId(LazychatMessage lazychatMessage) {
+ this.lazychatMessage = lazychatMessage;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public void setLanguage(String language) {
+ this.language = language;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof LazychatMessageTextPK)) {
+ return false;
+ }
+ LazychatMessageTextPK that = (LazychatMessageTextPK) o;
+ return Objects.equals(getLazychatMessage(), that.getLazychatMessage())
+ && getLanguage().equals(that.getLanguage());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getLazychatMessage(), getLanguage());
+ }
+}
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatResource.java b/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatResource.java
index 156b638..270a3d0 100644
--- a/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatResource.java
+++ b/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatResource.java
@@ -45,8 +45,7 @@ public class LazychatResource extends PostResource {
var user = Objects.requireNonNull(getCurrentUser());
var message = new LazychatMessage();
- message.content = text;
- message.format = "markdown";
+ message.setContent(text);
message.owner = user;
message.date = OffsetDateTime.now();
@@ -81,9 +80,7 @@ public class LazychatResource extends PostResource {
throw new ForbiddenException();
}
- message.content = text;
- message.cachedDescriptionHtml = null;
- message.format = "markdown";
+ message.setContent(text);
assignPostTargets(visibility, user, message);
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 2bd9ade..8f2166c 100644
--- a/src/main/java/eu/mulk/mulkcms2/benki/posts/Post.java
+++ b/src/main/java/eu/mulk/mulkcms2/benki/posts/Post.java
@@ -1,5 +1,7 @@
package eu.mulk.mulkcms2.benki.posts;
+import static java.util.stream.Collectors.toList;
+
import eu.mulk.mulkcms2.benki.accesscontrol.Role;
import eu.mulk.mulkcms2.benki.bookmarks.Bookmark;
import eu.mulk.mulkcms2.benki.lazychat.LazychatMessage;
@@ -10,7 +12,9 @@ import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TimeZone;
@@ -18,6 +22,7 @@ import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import javax.json.bind.annotation.JsonbTransient;
+import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@@ -30,6 +35,8 @@ import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
+import javax.persistence.MapKey;
+import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.criteria.CriteriaBuilder;
@@ -43,12 +50,10 @@ import org.jboss.logging.Logger;
@Entity
@Table(name = "posts", schema = "benki")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
-public abstract class Post extends PanacheEntityBase {
+public abstract class Post<Text extends PostText<?>> extends PanacheEntityBase {
private static final Logger log = Logger.getLogger(Post.class);
- private static final int DESCRIPTION_CACHE_VERSION = 1;
-
@Id
@SequenceGenerator(
allocationSize = 1,
@@ -63,14 +68,6 @@ public abstract class Post extends PanacheEntityBase {
@CheckForNull
public OffsetDateTime date;
- @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)
@JoinColumn(name = "owner", referencedColumnName = "id")
@CheckForNull
@@ -95,6 +92,18 @@ public abstract class Post extends PanacheEntityBase {
@JsonbTransient
public Set<Role> targets;
+ @OneToMany(
+ mappedBy = "post",
+ fetch = FetchType.LAZY,
+ cascade = CascadeType.ALL,
+ targetEntity = PostText.class)
+ @MapKey(name = "language")
+ public Map<String, Text> texts = new HashMap<>();
+
+ public Map<String, Text> getTexts() {
+ return texts;
+ }
+
public abstract boolean isBookmark();
public abstract boolean isLazychatMessage();
@@ -103,23 +112,6 @@ public abstract class Post extends PanacheEntityBase {
public abstract String getTitle();
@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();
-
- @CheckForNull
public abstract String getUri();
public Visibility getVisibility() {
@@ -195,7 +187,16 @@ public abstract class Post extends PanacheEntityBase {
return getVisibility() == Visibility.PUBLIC || (user != null && visibleTo.contains(user));
}
- public static class PostPage<T extends Post> {
+ @CheckForNull
+ public final String getDescriptionHtml() {
+ var text = getText();
+ if (text == null) {
+ return null;
+ }
+ return text.getDescriptionHtml();
+ }
+
+ public static class PostPage<T extends Post<? extends PostText>> {
public @CheckForNull final Integer prevCursor;
public @CheckForNull final Integer cursor;
public @CheckForNull final Integer nextCursor;
@@ -229,7 +230,7 @@ public abstract class Post extends PanacheEntityBase {
public void cacheDescriptions() {
for (var post : posts) {
- post.getDescriptionHtml();
+ post.getTexts().values().forEach(PostText::getDescriptionHtml);
}
}
}
@@ -245,12 +246,12 @@ public abstract class Post extends PanacheEntityBase {
}
}
- public static PostPage<Post> findViewable(
+ public static PostPage<Post<? extends PostText>> findViewable(
PostFilter postFilter, Session session, @CheckForNull User viewer, @CheckForNull User owner) {
return findViewable(postFilter, session, viewer, owner, null, null);
}
- public static PostPage<Post> findViewable(
+ public static PostPage<Post<? extends PostText>> findViewable(
PostFilter postFilter,
Session session,
@CheckForNull User viewer,
@@ -271,7 +272,7 @@ public abstract class Post extends PanacheEntityBase {
return findViewable(entityClass, session, viewer, owner, cursor, count);
}
- protected static <T extends Post> PostPage<T> findViewable(
+ protected static <T extends Post<? extends PostText>> PostPage<T> findViewable(
Class<? extends T> entityClass,
Session session,
@CheckForNull User viewer,
@@ -316,9 +317,31 @@ public abstract class Post extends PanacheEntityBase {
}
}
+ // Fetch texts (to avoid n+1 selects).
+ var postIds = forwardResults.stream().map(x -> x.id).collect(toList());
+
+ if (!postIds.isEmpty()) {
+ find("SELECT p FROM Post p LEFT JOIN FETCH p.texts WHERE p.id IN (?1)", postIds).stream()
+ .count();
+ }
+
return new PostPage<>(prevCursor, cursor, nextCursor, forwardResults);
}
+ @CheckForNull
+ protected Text getText() {
+ var texts = getTexts();
+ if (texts.isEmpty()) {
+ return null;
+ } else if (texts.containsKey("")) {
+ return texts.get("");
+ } else if (texts.containsKey("en")) {
+ return texts.get("en");
+ } else {
+ return texts.values().stream().findAny().get();
+ }
+ }
+
public enum Visibility {
PUBLIC,
SEMIPRIVATE,
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();
+}
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/posts/PostTextPK.java b/src/main/java/eu/mulk/mulkcms2/benki/posts/PostTextPK.java
new file mode 100644
index 0000000..0a945dd
--- /dev/null
+++ b/src/main/java/eu/mulk/mulkcms2/benki/posts/PostTextPK.java
@@ -0,0 +1,55 @@
+package eu.mulk.mulkcms2.benki.posts;
+
+import java.io.Serializable;
+import java.util.Objects;
+import javax.persistence.Column;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+@IdClass(PostTextPK.class)
+public class PostTextPK implements Serializable {
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "post", referencedColumnName = "id", nullable = false)
+ public Post<?> post;
+
+ @Id
+ @Column(name = "language", nullable = false, length = -1)
+ private String language;
+
+ public Post<?> getPost() {
+ return post;
+ }
+
+ public void setPost(Post post) {
+ this.post = post;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public void setLanguage(String language) {
+ this.language = language;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof PostTextPK)) {
+ return false;
+ }
+ PostTextPK that = (PostTextPK) o;
+ return Objects.equals(getPost(), that.getPost()) && getLanguage().equals(that.getLanguage());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getPost(), getLanguage());
+ }
+}