aboutsummaryrefslogtreecommitdiff
path: root/juick-server/src/main/java/com/juick/service/TagServiceImpl.java
diff options
context:
space:
mode:
Diffstat (limited to 'juick-server/src/main/java/com/juick/service/TagServiceImpl.java')
-rw-r--r--juick-server/src/main/java/com/juick/service/TagServiceImpl.java190
1 files changed, 190 insertions, 0 deletions
diff --git a/juick-server/src/main/java/com/juick/service/TagServiceImpl.java b/juick-server/src/main/java/com/juick/service/TagServiceImpl.java
new file mode 100644
index 00000000..d63159cf
--- /dev/null
+++ b/juick-server/src/main/java/com/juick/service/TagServiceImpl.java
@@ -0,0 +1,190 @@
+package com.juick.service;
+
+import com.juick.Tag;
+import org.apache.commons.lang3.StringEscapeUtils;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.support.GeneratedKeyHolder;
+import org.springframework.jdbc.support.KeyHolder;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.Assert;
+
+import javax.inject.Inject;
+import java.sql.PreparedStatement;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * Created by aalexeev on 11/13/16.
+ */
+@Repository
+public class TagServiceImpl extends BaseJdbcService implements TagService {
+ private static final Pattern TAGS_PATTERN1 = Pattern.compile("^(?:(?:\\*[^ \\r\\n\\t]+)|\\s)+$");
+ private static final Pattern TAGS_PATTERN2 = Pattern.compile("^\\*([^ \\r\\n\\t]+)\\s+([\\s\\S]+)");
+ private static final Pattern TAG_PATTERN = Pattern.compile("\\*([^ \\r\\n\\t]+)");
+
+ private final MessagesService messagesService;
+
+ @Inject
+ public TagServiceImpl(JdbcTemplate jdbcTemplate, MessagesService messagesService) {
+ super(jdbcTemplate, null);
+ Assert.notNull(messagesService);
+ this.messagesService = messagesService;
+ }
+
+ @Transactional(readOnly = true)
+ @Override
+ public com.juick.Tag getTag(final int tid) {
+ try {
+ return getJdbcTemplate().queryForObject(
+ "SELECT synonym_id,name FROM tags WHERE tag_id=?",
+ (rs, num) -> {
+ Tag ret = new Tag(StringEscapeUtils.unescapeHtml4(rs.getString(2)));
+ ret.TID = tid;
+ ret.SynonymID = rs.getInt(1);
+ return ret;
+ },
+ tid);
+ } catch (EmptyResultDataAccessException e) {
+ return null;
+ }
+ }
+
+ @Transactional(readOnly = true)
+ @Override
+ public com.juick.Tag getTag(final String tag, final boolean autoCreate) {
+ Tag ret = null;
+ try {
+ ret = getJdbcTemplate().queryForObject(
+ "SELECT tag_id,synonym_id,name FROM tags WHERE name=?",
+ (rs, rowNum) -> {
+ Tag ret1 = new Tag(StringEscapeUtils.unescapeHtml4(rs.getString(3)));
+ ret1.TID = rs.getInt(1);
+ ret1.SynonymID = rs.getInt(2);
+ return ret1;
+ },
+ StringEscapeUtils.escapeHtml4(tag));
+ } catch (EmptyResultDataAccessException e) {
+ // tag not found
+ }
+ if (ret == null && autoCreate) {
+ ret = new com.juick.Tag(tag);
+ ret.TID = createTag(tag);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public List<Tag> getTags(final String[] tags, final boolean autoCreate) {
+ List<Tag> ret = new ArrayList<>();
+
+ for (String tag : tags) {
+ if (!tag.isEmpty()) {
+ Tag t = getTag(tag, autoCreate);
+ if (t != null) {
+ ret.add(t);
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ @Transactional(readOnly = true)
+ @Override
+ public boolean getTagNoIndex(final int tag_id) {
+ try {
+ return getJdbcTemplate().queryForObject(
+ "SELECT noindex FROM tags WHERE tag_id=?", Integer.class, tag_id) == 1;
+ } catch (EmptyResultDataAccessException e) {
+ return false;
+ }
+ }
+
+ @Transactional
+ @Override
+ public int createTag(final String name) {
+ KeyHolder holder = new GeneratedKeyHolder();
+ getJdbcTemplate().update(con -> {
+ PreparedStatement stmt = con.prepareStatement(
+ "INSERT INTO tags(name) VALUES (?)",
+ Statement.RETURN_GENERATED_KEYS);
+ stmt.setString(1, StringEscapeUtils.escapeHtml4(name));
+ return stmt;
+ }, holder);
+
+ return holder.getKey().intValue();
+ }
+
+ @Transactional(readOnly = true)
+ @Override
+ public List<com.juick.Tag> getUserTagsAll(final int uid) {
+ return getJdbcTemplate().query(
+ "SELECT tags.name,COUNT(messages.message_id) " +
+ "FROM (messages INNER JOIN messages_tags ON (messages.user_id=? " +
+ "AND messages.message_id=messages_tags.message_id)) " +
+ "INNER JOIN tags ON messages_tags.tag_id=tags.tag_id GROUP BY tags.tag_id ORDER BY tags.name ASC",
+ (rs, rowNum) -> {
+ Tag t = new Tag(StringEscapeUtils.unescapeHtml4(rs.getString(1)));
+ t.UsageCnt = rs.getInt(2);
+ return t;
+ }, uid);
+ }
+
+ @Transactional(readOnly = true)
+ @Override
+ public List<String> getUserBLTags(final int uid) {
+ return getJdbcTemplate().queryForList(
+ "SELECT tags.name FROM tags INNER JOIN bl_tags " +
+ "ON (bl_tags.user_id=? AND bl_tags.tag_id=tags.tag_id) ORDER BY tags.name",
+ String.class, uid);
+ }
+
+ @Transactional(readOnly = true)
+ @Override
+ public List<String> getPopularTags() {
+ return getJdbcTemplate().queryForList(
+ "SELECT name FROM tags WHERE top=1 ORDER BY name ASC", String.class).stream()
+ .map(StringEscapeUtils::unescapeHtml4).collect(Collectors.toList());
+ }
+
+ @Transactional
+ @Override
+ public List<Tag> updateTags(final int mid, final List<Tag> newTags) {
+ List<Tag> currentTags = messagesService.getMessageTags(mid);
+ newTags.stream().filter(currentTags::contains)
+ .forEach(t -> getJdbcTemplate().update(
+ "DELETE FROM messages_tags WHERE message_id=? AND tag_id=?",
+ mid,
+ t.TID));
+ newTags.stream().filter(t -> !currentTags.contains(t))
+ .forEach(t -> getJdbcTemplate().update(
+ "INSERT INTO messages_tags(message_id,tag_id) VALUES (?,?)", mid, t.TID));
+ return messagesService.getMessageTags(mid);
+ }
+
+ @Override
+ public List<Tag> fromString(final String txt, final boolean tagsOnly) {
+ Pattern tagsPattern = tagsOnly ? TAGS_PATTERN1 : TAGS_PATTERN2;
+
+ if (tagsPattern.matcher(txt).matches()) {
+ Matcher tagMatcher = TAG_PATTERN.matcher(txt);
+ List<Tag> tags = new ArrayList<>();
+ // TODO: process readonly, private, friends, public
+ while (tagMatcher.find()) {
+ for (int i = 1; i <= tagMatcher.groupCount(); i++) {
+ tags.add(getTag(tagMatcher.group(i), true));
+ }
+ }
+ return tags;
+ }
+ return Collections.emptyList();
+ }
+}