All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wallride.service.ArticleService Maven / Gradle / Ivy

/*
 * Copyright 2014 Tagbangers, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.wallride.service;

import org.apache.commons.lang.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.MessageCodesResolver;
import org.wallride.autoconfigure.WallRideCacheConfiguration;
import org.wallride.autoconfigure.WallRideProperties;
import org.wallride.domain.*;
import org.wallride.exception.DuplicateCodeException;
import org.wallride.exception.EmptyCodeException;
import org.wallride.exception.NotNullException;
import org.wallride.exception.ServiceException;
import org.wallride.model.*;
import org.wallride.repository.*;
import org.wallride.support.AuthorizedUser;
import org.wallride.support.CodeFormatter;
import org.wallride.web.controller.admin.article.CustomFieldValueEditForm;

import javax.annotation.Resource;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
@Transactional(rollbackFor=Exception.class)
public class ArticleService {

	@Resource
	private BlogService blogService;

	@Resource
	private PostRepository postRepository;

	@Resource
	private ArticleRepository articleRepository;

	@Resource
	private TagRepository tagRepository;

	@Resource
	private MediaRepository mediaRepository;

	@Inject
	private MessageCodesResolver messageCodesResolver;

	@Inject
	private PlatformTransactionManager transactionManager;

	@Inject
	private WallRideProperties wallRideProperties;

	@PersistenceContext
	private EntityManager entityManager;

	private static Logger logger = LoggerFactory.getLogger(ArticleService.class);

	@CacheEvict(value = WallRideCacheConfiguration.ARTICLE_CACHE, allEntries = true)
	public Article createArticle(ArticleCreateRequest request, Post.Status status, AuthorizedUser authorizedUser) {
		LocalDateTime now = LocalDateTime.now();

		String code = request.getCode();
		if (code == null) {
			try {
				code = new CodeFormatter().parse(request.getTitle(), LocaleContextHolder.getLocale());
			} catch (ParseException e) {
				throw new ServiceException(e);
			}
		}
		if (!StringUtils.hasText(code)) {
			if (!status.equals(Post.Status.DRAFT)) {
				throw new EmptyCodeException();
			}
		}

		if (!status.equals(Post.Status.DRAFT)) {
			Post duplicate = postRepository.findOneByCodeAndLanguage(code, request.getLanguage());
			if (duplicate != null) {
				throw new DuplicateCodeException(code);
			}
		}

		Article article = new Article();

		if (!status.equals(Post.Status.DRAFT)) {
			article.setCode(code);
			article.setDraftedCode(null);
		}
		else {
			article.setCode(null);
			article.setDraftedCode(code);
		}

		Media cover = null;
		if (request.getCoverId() != null) {
			cover = entityManager.getReference(Media.class, request.getCoverId());
		}
		article.setCover(cover);
		article.setTitle(request.getTitle());
		article.setBody(request.getBody());

		article.setAuthor(entityManager.getReference(User.class, authorizedUser.getId()));

		LocalDateTime date = request.getDate();
		if (Post.Status.PUBLISHED.equals(status)) {
			if (date == null) {
				date = now;
			}
			else if (date.isAfter(now)) {
				status = Post.Status.SCHEDULED;
			}
		}
		article.setDate(date);
		article.setStatus(status);
		article.setLanguage(request.getLanguage());

		article.getCategories().clear();
		for (long categoryId : request.getCategoryIds()) {
			article.getCategories().add(entityManager.getReference(Category.class, categoryId));
		}

		article.getTags().clear();
		Set tagNames = StringUtils.commaDelimitedListToSet(request.getTags());
		if (!CollectionUtils.isEmpty(tagNames)) {
			for (String tagName : tagNames) {
				Tag tag = tagRepository.findOneForUpdateByNameAndLanguage(tagName, request.getLanguage());
				if (tag == null) {
					tag = new Tag();
					tag.setName(tagName);
					tag.setLanguage(request.getLanguage());
					article.setCreatedAt(now);
					article.setCreatedBy(authorizedUser.toString());
					article.setUpdatedAt(now);
					article.setUpdatedBy(authorizedUser.toString());
					tag = tagRepository.saveAndFlush(tag);
				}
				article.getTags().add(tag);
			}
		}

		article.getRelatedPosts().clear();
		Set relatedPosts = new HashSet<>();
		for (long relatedId : request.getRelatedPostIds()) {
			relatedPosts.add(entityManager.getReference(Post.class, relatedId));
		}
		article.setRelatedToPosts(relatedPosts);

		Seo seo = new Seo();
		seo.setTitle(request.getSeoTitle());
		seo.setDescription(request.getSeoDescription());
		seo.setKeywords(request.getSeoKeywords());
		article.setSeo(seo);

		List medias = new ArrayList<>();
		if (StringUtils.hasText(request.getBody())) {
//			Blog blog = blogService.getBlogById(Blog.DEFAULT_ID);
			String mediaUrlPrefix = wallRideProperties.getMediaUrlPrefix();
			Pattern mediaUrlPattern = Pattern.compile(String.format("%s([0-9a-zA-Z\\-]+)", mediaUrlPrefix));
			Matcher mediaUrlMatcher = mediaUrlPattern.matcher(request.getBody());
			while (mediaUrlMatcher.find()) {
				Media media = mediaRepository.findOneById(mediaUrlMatcher.group(1));
				medias.add(media);
			}
		}
		article.setMedias(medias);

		article.setCreatedAt(now);
		article.setCreatedBy(authorizedUser.toString());
		article.setUpdatedAt(now);
		article.setUpdatedBy(authorizedUser.toString());

		article.getCustomFieldValues().clear();
		if (!CollectionUtils.isEmpty(request.getCustomFieldValues())) {
			for (CustomFieldValueEditForm valueForm : request.getCustomFieldValues()) {
				CustomFieldValue value =  new CustomFieldValue();
				value.setCustomField(entityManager.getReference(CustomField.class, valueForm.getCustomFieldId()));
				value.setPost(article);
				if (valueForm.getFieldType().equals(CustomField.FieldType.CHECKBOX)) {
					if (!ArrayUtils.isEmpty(valueForm.getTextValues())) {
						value.setTextValue(String.join(",", valueForm.getTextValues()));
					} else {
						value.setTextValue(null);
					}
				} else {
					value.setTextValue(valueForm.getTextValue());
				}
				value.setStringValue(valueForm.getStringValue());
				value.setNumberValue(valueForm.getNumberValue());
				value.setDateValue(valueForm.getDateValue());
				value.setDatetimeValue(valueForm.getDatetimeValue());
				if (!value.isEmpty()) {
					article.getCustomFieldValues().add(value);
				}
			}
		}
		return articleRepository.save(article);
	}

	@CacheEvict(value = WallRideCacheConfiguration.ARTICLE_CACHE, allEntries = true)
	public Article saveArticleAsDraft(ArticleUpdateRequest request, AuthorizedUser authorizedUser) {
		postRepository.lock(request.getId());
		Article article = articleRepository.findOneByIdAndLanguage(request.getId(), request.getLanguage());
		if (!article.getStatus().equals(Post.Status.DRAFT)) {
			Article draft = articleRepository.findOne(ArticleSpecifications.draft(article));
			if (draft == null) {
				ArticleCreateRequest createRequest = new ArticleCreateRequest.Builder()
						.code(request.getCode())
						.coverId(request.getCoverId())
						.title(request.getTitle())
						.body(request.getBody())
						.authorId(request.getAuthorId())
						.date(request.getDate())
						.categoryIds(request.getCategoryIds())
						.tags(request.getTags())
						.seoTitle(request.getSeoTitle())
						.seoDescription(request.getSeoDescription())
						.seoKeywords(request.getSeoKeywords())
						.customFieldValues(new ArrayList<>(request.getCustomFieldValues()))
						.language(request.getLanguage())
						.build();
				draft = createArticle(createRequest, Post.Status.DRAFT, authorizedUser);
				draft.setDrafted(article);
				return articleRepository.save(draft);
			}
			else {
				ArticleUpdateRequest updateRequest = new ArticleUpdateRequest.Builder()
						.id(draft.getId())
						.code(request.getCode())
						.coverId(request.getCoverId())
						.title(request.getTitle())
						.body(request.getBody())
						.authorId(request.getAuthorId())
						.date(request.getDate())
						.categoryIds(request.getCategoryIds())
						.tags(request.getTags())
						.seoTitle(request.getSeoTitle())
						.seoDescription(request.getSeoDescription())
						.seoKeywords(request.getSeoKeywords())
						.customFieldValues(request.getCustomFieldValues())
						.language(request.getLanguage())
						.build();
				return saveArticle(updateRequest, authorizedUser);
			}
		}
		else {
			return saveArticle(request, authorizedUser);
		}
	}

	@CacheEvict(value = WallRideCacheConfiguration.ARTICLE_CACHE, allEntries = true)
	public Article saveArticleAsPublished(ArticleUpdateRequest request, AuthorizedUser authorizedUser) {
		postRepository.lock(request.getId());
		Article article = articleRepository.findOneByIdAndLanguage(request.getId(), request.getLanguage());
		publishArticle(article);
		return saveArticle(request, authorizedUser);
	}

	private Article publishArticle(Article article) {
		Article deleteTarget = getDraftById(article.getId());
		if (deleteTarget != null) {
			articleRepository.delete(deleteTarget);
		}
		article.setDrafted(null);
		article.setStatus(Post.Status.PUBLISHED);
		Article published = articleRepository.save(article);
		return published;
	}

	@CacheEvict(value = WallRideCacheConfiguration.ARTICLE_CACHE, allEntries = true)
	public Article saveArticleAsUnpublished(ArticleUpdateRequest request, AuthorizedUser authorizedUser) {
		postRepository.lock(request.getId());
		Article article = articleRepository.findOneByIdAndLanguage(request.getId(), request.getLanguage());
		unpublishArticle(article);
		return saveArticle(request, authorizedUser);
	}

	private Article unpublishArticle(Article article) {
		Article deleteTarget = getDraftById(article.getId());
		if (deleteTarget != null) {
			articleRepository.delete(deleteTarget);
		}
		article.setDrafted(null);
		article.setStatus(Post.Status.DRAFT);
		Article unpublished = articleRepository.save(article);
		return unpublished;
	}

	@CacheEvict(value = WallRideCacheConfiguration.ARTICLE_CACHE, allEntries = true)
	public Article saveArticle(ArticleUpdateRequest request, AuthorizedUser authorizedUser) {
		postRepository.lock(request.getId());
		Article article = articleRepository.findOneByIdAndLanguage(request.getId(), request.getLanguage());
		LocalDateTime now = LocalDateTime.now();

		String code = request.getCode();
		if (code == null) {
			try {
				code = new CodeFormatter().parse(request.getTitle(), LocaleContextHolder.getLocale());
			} catch (ParseException e) {
				throw new ServiceException(e);
			}
		}
		if (!StringUtils.hasText(code)) {
			if (!article.getStatus().equals(Post.Status.DRAFT)) {
				throw new EmptyCodeException();
			}
		}
		if (!article.getStatus().equals(Post.Status.DRAFT)) {
			Post duplicate = postRepository.findOneByCodeAndLanguage(code, request.getLanguage());
			if (duplicate != null && !duplicate.equals(article)) {
				throw new DuplicateCodeException(code);
			}
		}

		if (!article.getStatus().equals(Post.Status.DRAFT)) {
			article.setCode(code);
			article.setDraftedCode(null);
		}
		else {
			article.setCode(null);
			article.setDraftedCode(code);
		}

		Media cover = null;
		if (request.getCoverId() != null) {
			cover = entityManager.getReference(Media.class, request.getCoverId());
		}
		article.setCover(cover);
		article.setTitle(request.getTitle());
		article.setBody(request.getBody());

//		User author = null;
//		if (request.getAuthorId() != null) {
//			author = entityManager.getReference(User.class, request.getAuthorId());
//		}
//		article.setAuthor(author);

		LocalDateTime date = request.getDate();
		if (!Post.Status.DRAFT.equals(article.getStatus())) {
			if (date == null) {
				date = now;
			} else if (date.isAfter(now)) {
				article.setStatus(Post.Status.SCHEDULED);
			} else {
				article.setStatus(Post.Status.PUBLISHED);
			}
		}
		article.setDate(date);
		article.setLanguage(request.getLanguage());

		article.getCategories().clear();
		for (long categoryId : request.getCategoryIds()) {
			article.getCategories().add(entityManager.getReference(Category.class, categoryId));
		}

		article.getTags().clear();
		Set tagNames = StringUtils.commaDelimitedListToSet(request.getTags());
		if (!CollectionUtils.isEmpty(tagNames)) {
			for (String tagName : tagNames) {
				Tag tag = tagRepository.findOneForUpdateByNameAndLanguage(tagName, request.getLanguage());
				if (tag == null) {
					tag = new Tag();
					tag.setName(tagName);
					tag.setLanguage(request.getLanguage());
					article.setCreatedAt(now);
					article.setCreatedBy(authorizedUser.toString());
					article.setUpdatedAt(now);
					article.setUpdatedBy(authorizedUser.toString());
					tag = tagRepository.saveAndFlush(tag);
				}
				article.getTags().add(tag);
			}
		}

		article.getRelatedPosts().clear();
		Set relatedPosts = new HashSet<>();
		for (long relatedId : request.getRelatedPostIds()) {
			relatedPosts.add(entityManager.getReference(Post.class, relatedId));
		}
		article.setRelatedToPosts(relatedPosts);

		Seo seo = new Seo();
		seo.setTitle(request.getSeoTitle());
		seo.setDescription(request.getSeoDescription());
		seo.setKeywords(request.getSeoKeywords());
		article.setSeo(seo);

		List medias = new ArrayList<>();
		if (StringUtils.hasText(request.getBody())) {
//			Blog blog = blogService.getBlogById(Blog.DEFAULT_ID);
			String mediaUrlPrefix = wallRideProperties.getMediaUrlPrefix();
			Pattern mediaUrlPattern = Pattern.compile(String.format("%s([0-9a-zA-Z\\-]+)", mediaUrlPrefix));
			Matcher mediaUrlMatcher = mediaUrlPattern.matcher(request.getBody());
			while (mediaUrlMatcher.find()) {
				Media media = mediaRepository.findOneById(mediaUrlMatcher.group(1));
				medias.add(media);
			}
		}
		article.setMedias(medias);

		article.setUpdatedAt(now);
		article.setUpdatedBy(authorizedUser.toString());

		Map valueMap = new LinkedHashMap<>();
		for (CustomFieldValue value : article.getCustomFieldValues()) {
			valueMap.put(value.getCustomField(), value);
		}

		article.getCustomFieldValues().clear();
		if (!CollectionUtils.isEmpty(request.getCustomFieldValues())) {
			for (CustomFieldValueEditForm valueForm : request.getCustomFieldValues()) {
				CustomField customField = entityManager.getReference(CustomField.class, valueForm.getCustomFieldId());
				CustomFieldValue value = valueMap.get(customField);
				if (value == null) {
					value = new CustomFieldValue();
				}
				value.setCustomField(customField);
				value.setPost(article);
				if (valueForm.getFieldType().equals(CustomField.FieldType.CHECKBOX)) {
					if (!ArrayUtils.isEmpty(valueForm.getTextValues())) {
						value.setTextValue(String.join(",", valueForm.getTextValues()));
					} else {
						value.setTextValue(null);
					}
				} else {
					value.setTextValue(valueForm.getTextValue());
				}
				value.setStringValue(valueForm.getStringValue());
				value.setNumberValue(valueForm.getNumberValue());
				value.setDateValue(valueForm.getDateValue());
				value.setDatetimeValue(valueForm.getDatetimeValue());
				if (!value.isEmpty()) {
					article.getCustomFieldValues().add(value);
				}
			}
		}

		return articleRepository.save(article);
	}

	@CacheEvict(value = WallRideCacheConfiguration.ARTICLE_CACHE, allEntries = true)
	public Article deleteArticle(ArticleDeleteRequest request, BindingResult result) throws BindException {
		postRepository.lock(request.getId());
		Article article = articleRepository.findOneByIdAndLanguage(request.getId(), request.getLanguage());
		articleRepository.delete(article);
		return article;
	}

	@CacheEvict(value = WallRideCacheConfiguration.ARTICLE_CACHE, allEntries = true)
	public List
bulkPublishArticle(ArticleBulkPublishRequest request, AuthorizedUser authorizedUser) { List
articles = new ArrayList<>(); for (long id : request.getIds()) { postRepository.lock(id); Article article = articleRepository.findOneByIdAndLanguage(id, request.getLanguage()); if (article.getStatus() != Post.Status.DRAFT && request.getDate() == null) { continue; } if (!StringUtils.hasText(article.getCode())) { throw new NotNullException(); } if (!StringUtils.hasText(article.getTitle())) { throw new NotNullException(); } if (!StringUtils.hasText(article.getBody())) { throw new NotNullException(); } LocalDateTime now = LocalDateTime.now(); LocalDateTime date = article.getDate(); if (request.getDate() != null) { date = request.getDate(); } if (date == null) { date = now; } article.setDate(date); article.setUpdatedAt(now); article.setUpdatedBy(authorizedUser.toString()); article = publishArticle(article); if (article.getDate().isAfter(now)) { article.setStatus(Post.Status.SCHEDULED); } else { article.setStatus(Post.Status.PUBLISHED); } article = articleRepository.saveAndFlush(article); articles.add(article); } return articles; } @CacheEvict(value = WallRideCacheConfiguration.ARTICLE_CACHE, allEntries = true) public List
bulkUnpublishArticle(ArticleBulkUnpublishRequest request, AuthorizedUser authorizedUser) { List
articles = new ArrayList<>(); for (long id : request.getIds()) { postRepository.lock(id); Article article = articleRepository.findOneByIdAndLanguage(id, request.getLanguage()); if (article.getStatus() == Post.Status.DRAFT) { continue; } LocalDateTime now = LocalDateTime.now(); article.setUpdatedAt(now); article.setUpdatedBy(authorizedUser.toString()); article = unpublishArticle(article); articles.add(article); } return articles; } @Transactional(propagation=Propagation.NOT_SUPPORTED) @CacheEvict(value = WallRideCacheConfiguration.ARTICLE_CACHE, allEntries = true) public List
bulkDeleteArticle(ArticleBulkDeleteRequest bulkDeleteRequest, BindingResult result) { List
articles = new ArrayList<>(); for (long id : bulkDeleteRequest.getIds()) { final ArticleDeleteRequest deleteRequest = new ArticleDeleteRequest.Builder() .id(id) .language(bulkDeleteRequest.getLanguage()) .build(); final BeanPropertyBindingResult r = new BeanPropertyBindingResult(deleteRequest, "request"); r.setMessageCodesResolver(messageCodesResolver); TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); transactionTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW); Article article = null; try { article = transactionTemplate.execute(new TransactionCallback
() { public Article doInTransaction(TransactionStatus status) { try { return deleteArticle(deleteRequest, r); } catch (BindException e) { throw new RuntimeException(e); } } }); articles.add(article); } catch (Exception e) { logger.debug("Errors: {}", r); result.addAllErrors(r); } } return articles; } public List getArticleIds(ArticleSearchRequest request) { return articleRepository.searchForId(request); } public Page
getArticles(ArticleSearchRequest request) { Pageable pageable = new PageRequest(0, 10); return getArticles(request, pageable); } @Cacheable(value = WallRideCacheConfiguration.ARTICLE_CACHE) public Page
getArticles(ArticleSearchRequest request, Pageable pageable) { return articleRepository.search(request, pageable); } public List
getArticles(Collection ids) { Set
results = new LinkedHashSet
(articleRepository.findAllByIdIn(ids)); List
articles = new ArrayList<>(); for (long id : ids) { for (Article article : results) { if (id == article.getId()) { articles.add(article); break; } } } return articles; } @Cacheable(value = WallRideCacheConfiguration.ARTICLE_CACHE) public SortedSet
getArticlesByCategoryCode(String language, String code, Post.Status status) { return getArticlesByCategoryCode(language, code, status, 10); } @Cacheable(value = WallRideCacheConfiguration.ARTICLE_CACHE) public SortedSet
getArticlesByCategoryCode(String language, String code, Post.Status status, int size) { ArticleSearchRequest request = new ArticleSearchRequest() .withLanguage(language) .withCategoryCodes(code) .withStatus(status); Pageable pageable = new PageRequest(0, size); Page
page = articleRepository.search(request, pageable); return new TreeSet<>(page.getContent()); } @Cacheable(value = WallRideCacheConfiguration.ARTICLE_CACHE) public SortedSet
getLatestArticles(String language, Post.Status status, int size) { ArticleSearchRequest request = new ArticleSearchRequest() .withLanguage(language) .withStatus(status); Pageable pageable = new PageRequest(0, size); Page
page = articleRepository.search(request, pageable); return new TreeSet<>(page.getContent()); } public Article getArticleById(long id) { return articleRepository.findOneById(id); } public Article getArticleById(long id, String language) { return articleRepository.findOneByIdAndLanguage(id, language); } @Cacheable(value = WallRideCacheConfiguration.ARTICLE_CACHE) public Article getArticleByCode(String code, String language) { return articleRepository.findOneByCodeAndLanguage(code, language); } public Article getDraftById(long id) { return articleRepository.findOne(ArticleSpecifications.draft(entityManager.getReference(Article.class, id))); } public long countArticles(String language) { return articleRepository.count(language); } public long countArticlesByStatus(Post.Status status, String language) { return articleRepository.countByStatus(status, language); } public Map countArticlesByAuthorIdGrouped(Post.Status status, String language) { List> results = articleRepository.countByAuthorIdGrouped(status, language); Map counts = new HashMap<>(); for (Map row : results) { counts.put((Long) row.get("userId"), (Long) row.get("count")); } return counts; } public Map countArticlesByCategoryIdGrouped(Post.Status status, String language) { List> results = articleRepository.countByCategoryIdGrouped(status, language); Map counts = new HashMap<>(); for (Map row : results) { counts.put((Long) row.get("categoryId"), (Long) row.get("count")); } return counts; } public Map countArticlesByTagIdGrouped(Post.Status status, String language) { List> results = articleRepository.countByTagIdGrouped(status, language); Map counts = new HashMap<>(); for (Map row : results) { counts.put((Long) row.get("tagId"), (Long) row.get("count")); } return counts; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy