org.wallride.service.PageService.java Source code

Java tutorial

Introduction

Here is the source code for org.wallride.service.PageService.java

Source

/*
 * 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.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.ObjectUtils;
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.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.time.temporal.ChronoUnit;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

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

    @Resource
    private PostRepository postRepository;

    @Resource
    private PageRepository pageRepository;

    @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(PageService.class);

    @CacheEvict(value = WallRideCacheConfiguration.PAGE_CACHE, allEntries = true)
    public Page createPage(PageCreateRequest 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);
            }
        }

        Page page = new Page();

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

        Page parent = (request.getParentId() != null)
                ? pageRepository.findOneByIdAndLanguage(request.getParentId(), request.getLanguage())
                : null;
        int rgt = 0;
        if (parent == null) {
            rgt = pageRepository.findMaxRgt();
            rgt++;
        } else {
            rgt = parent.getRgt();
            pageRepository.unshiftRgt(rgt);
            pageRepository.unshiftLft(rgt);
        }

        page.setParent(parent);

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

        page.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;
            }
        }
        page.setDate(date);
        page.setStatus(status);
        page.setLanguage(request.getLanguage());

        page.getCategories().clear();
        SortedSet<Category> categories = new TreeSet<>();
        for (long categoryId : request.getCategoryIds()) {
            categories.add(entityManager.getReference(Category.class, categoryId));
        }
        page.setCategories(categories);

        page.getTags().clear();
        Set<String> 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());
                    page.setCreatedAt(now);
                    page.setCreatedBy(authorizedUser.toString());
                    page.setUpdatedAt(now);
                    page.setUpdatedBy(authorizedUser.toString());
                    tag = tagRepository.saveAndFlush(tag);
                }
                page.getTags().add(tag);
            }
        }

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

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

        page.setLft(rgt);
        page.setRgt(rgt + 1);

        List<Media> 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);
            }
        }
        page.setMedias(medias);

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

        page.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(page);
                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()) {
                    page.getCustomFieldValues().add(value);
                }
            }
        }

        return pageRepository.save(page);
    }

    @CacheEvict(value = WallRideCacheConfiguration.PAGE_CACHE, allEntries = true)
    public Page savePageAsDraft(PageUpdateRequest request, AuthorizedUser authorizedUser) {
        postRepository.lock(request.getId());
        Page page = pageRepository.findOneByIdAndLanguage(request.getId(), request.getLanguage());
        if (!page.getStatus().equals(Post.Status.DRAFT)) {
            Page draft = pageRepository.findOne(PageSpecifications.draft(page));
            if (draft == null) {
                PageCreateRequest createRequest = new PageCreateRequest.Builder().code(request.getCode())
                        .coverId(request.getCoverId()).title(request.getTitle()).body(request.getBody())
                        .authorId(request.getAuthorId()).date(request.getDate()).parentId(request.getParentId())
                        .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 = createPage(createRequest, Post.Status.DRAFT, authorizedUser);
                draft.setDrafted(page);
                return pageRepository.save(draft);
            } else {
                PageUpdateRequest updateRequest = new PageUpdateRequest.Builder().id(draft.getId())
                        .code(request.getCode()).coverId(request.getCoverId()).title(request.getTitle())
                        .body(request.getBody()).authorId(request.getAuthorId()).date(request.getDate())
                        .parentId(request.getParentId()).categoryIds(request.getCategoryIds())
                        .tags(request.getTags()).seoTitle(request.getSeoTitle())
                        .seoDescription(request.getSeoDescription()).seoKeywords(request.getSeoKeywords())
                        .customFieldValues(request.getCustomFieldValues()).language(request.getLanguage()).build();
                return savePage(updateRequest, authorizedUser);
            }
        } else {
            return savePage(request, authorizedUser);
        }
    }

    @CacheEvict(value = WallRideCacheConfiguration.PAGE_CACHE, allEntries = true)
    public Page savePageAsPublished(PageUpdateRequest request, AuthorizedUser authorizedUser) {
        postRepository.lock(request.getId());
        Page page = pageRepository.findOneByIdAndLanguage(request.getId(), request.getLanguage());
        Page deleteTarget = getDraftById(page.getId());
        if (deleteTarget != null) {
            pageRepository.delete(deleteTarget);
        }
        page.setDrafted(null);
        page.setStatus(Post.Status.PUBLISHED);
        pageRepository.save(page);
        return savePage(request, authorizedUser);
    }

    @CacheEvict(value = WallRideCacheConfiguration.PAGE_CACHE, allEntries = true)
    public Page savePageAsUnpublished(PageUpdateRequest request, AuthorizedUser authorizedUser) {
        postRepository.lock(request.getId());
        Page page = pageRepository.findOneByIdAndLanguage(request.getId(), request.getLanguage());
        Page deleteTarget = getDraftById(page.getId());
        if (deleteTarget != null) {
            pageRepository.delete(deleteTarget);
        }
        page.setDrafted(null);
        page.setStatus(Post.Status.DRAFT);
        pageRepository.save(page);
        pageRepository.deleteByDrafted(page);
        return savePage(request, authorizedUser);
    }

    @CacheEvict(value = WallRideCacheConfiguration.PAGE_CACHE, allEntries = true)
    public Page savePage(PageUpdateRequest request, AuthorizedUser authorizedUser) {
        postRepository.lock(request.getId());
        Page page = pageRepository.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 (!page.getStatus().equals(Post.Status.DRAFT)) {
                throw new EmptyCodeException();
            }
        }
        if (!page.getStatus().equals(Post.Status.DRAFT)) {
            Post duplicate = postRepository.findOneByCodeAndLanguage(code, request.getLanguage());
            if (duplicate != null && !duplicate.equals(page)) {
                throw new DuplicateCodeException(code);
            }
        }

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

        Page parent = (request.getParentId() != null)
                ? entityManager.getReference(Page.class, request.getParentId())
                : null;
        if (!(page.getParent() == null && parent == null)
                && !ObjectUtils.nullSafeEquals(page.getParent(), parent)) {
            pageRepository.shiftLftRgt(page.getLft(), page.getRgt());
            pageRepository.shiftRgt(page.getRgt());
            pageRepository.shiftLft(page.getRgt());

            int rgt = 0;
            if (parent == null) {
                rgt = pageRepository.findMaxRgt();
                rgt++;
            } else {
                rgt = parent.getRgt();
                pageRepository.unshiftRgt(rgt);
                pageRepository.unshiftLft(rgt);
            }
            page.setLft(rgt);
            page.setRgt(rgt + 1);
        }

        page.setParent(parent);

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

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

        LocalDateTime date = request.getDate();
        if (Post.Status.PUBLISHED.equals(page.getStatus())) {
            if (date == null) {
                date = now.truncatedTo(ChronoUnit.HOURS);
            } else if (date.isAfter(now)) {
                page.setStatus(Post.Status.SCHEDULED);
            }
        }
        page.setDate(date);
        page.setLanguage(request.getLanguage());

        page.getCategories().clear();
        SortedSet<Category> categories = new TreeSet<>();
        for (long categoryId : request.getCategoryIds()) {
            categories.add(entityManager.getReference(Category.class, categoryId));
        }
        page.setCategories(categories);

        page.getTags().clear();
        Set<String> 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());
                    page.setCreatedAt(now);
                    page.setCreatedBy(authorizedUser.toString());
                    page.setUpdatedAt(now);
                    page.setUpdatedBy(authorizedUser.toString());
                    tag = tagRepository.saveAndFlush(tag);
                }
                page.getTags().add(tag);
            }
        }

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

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

        List<Media> 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);
            }
        }
        page.setMedias(medias);

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

        SortedSet<CustomFieldValue> fieldValues = new TreeSet<>();
        Map<CustomField, CustomFieldValue> valueMap = new LinkedHashMap<>();
        for (CustomFieldValue value : page.getCustomFieldValues()) {
            valueMap.put(value.getCustomField(), value);
        }

        page.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(page);
                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()) {
                    fieldValues.add(value);
                }
            }
        }
        page.setCustomFieldValues(fieldValues);

        return pageRepository.save(page);
    }

    @CacheEvict(value = WallRideCacheConfiguration.PAGE_CACHE, allEntries = true)
    public void updatePageHierarchy(List<Map<String, Object>> data, String language) {
        for (int i = 0; i < data.size(); i++) {
            Map<String, Object> map = data.get(i);
            if (map.get("item_id") != null) {
                postRepository.lock(Long.parseLong((String) map.get("item_id")));
                Page page = pageRepository.findOneByIdAndLanguage(Long.parseLong((String) map.get("item_id")),
                        language);
                if (page != null) {
                    Page parent = null;
                    if (map.get("parent_id") != null) {
                        parent = pageRepository
                                .findOneByIdAndLanguage(Long.parseLong((String) map.get("parent_id")), language);
                    }
                    page.setParent(parent);
                    page.setLft(((int) map.get("left")) - 1);
                    page.setRgt(((int) map.get("right")) - 1);
                    //               page.setDepth((int) map.get("depth"));
                    //               page.setSort(i);
                    pageRepository.save(page);
                }
            }
        }
    }

    @CacheEvict(value = WallRideCacheConfiguration.PAGE_CACHE, allEntries = true)
    public Page deletePage(PageDeleteRequest request, BindingResult result) throws BindException {
        postRepository.lock(request.getId());
        Page page = pageRepository.findOneByIdAndLanguage(request.getId(), request.getLanguage());
        Page parent = page.getParent();
        for (Page child : page.getChildren()) {
            child.setParent(parent);
            pageRepository.saveAndFlush(child);
        }
        page.getChildren().clear();
        pageRepository.saveAndFlush(page);
        pageRepository.delete(page);

        pageRepository.shiftLftRgt(page.getLft(), page.getRgt());
        pageRepository.shiftRgt(page.getRgt());
        pageRepository.shiftLft(page.getRgt());

        return page;
    }

    @CacheEvict(value = WallRideCacheConfiguration.PAGE_CACHE, allEntries = true)
    public Page deletePage(long id, String language) {
        postRepository.lock(id);
        Page page = pageRepository.findOneByIdAndLanguage(id, language);
        Page parent = page.getParent();
        for (Page child : page.getChildren()) {
            child.setParent(parent);
            pageRepository.saveAndFlush(child);
        }
        page.getChildren().clear();
        pageRepository.saveAndFlush(page);
        pageRepository.delete(page);

        pageRepository.shiftLftRgt(page.getLft(), page.getRgt());
        pageRepository.shiftRgt(page.getRgt());
        pageRepository.shiftLft(page.getRgt());

        return page;
    }

    @CacheEvict(value = WallRideCacheConfiguration.PAGE_CACHE, allEntries = true)
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<Page> bulkDeletePage(PageBulkDeleteRequest bulkDeleteRequest, BindingResult result) {
        List<Page> pages = new ArrayList<>();
        for (long id : bulkDeleteRequest.getIds()) {
            final PageDeleteRequest deleteRequest = new PageDeleteRequest.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);
            Page page = null;
            try {
                page = transactionTemplate.execute(new TransactionCallback<Page>() {
                    public Page doInTransaction(TransactionStatus status) {
                        try {
                            return deletePage(deleteRequest, r);
                        } catch (BindException e) {
                            throw new RuntimeException(e);
                        }
                    }
                });
                pages.add(page);
            } catch (Exception e) {
                logger.debug("Errors: {}", r);
                result.addAllErrors(r);
            }
        }
        return pages;
    }

    public List<Long> getPageIds(PageSearchRequest request) {
        return pageRepository.searchForId(request);
    }

    @Cacheable(value = WallRideCacheConfiguration.PAGE_CACHE)
    public org.springframework.data.domain.Page<Page> getPages(PageSearchRequest request) {
        return getPages(request, null);
    }

    @Cacheable(value = WallRideCacheConfiguration.PAGE_CACHE)
    public org.springframework.data.domain.Page<Page> getPages(PageSearchRequest request, Pageable pageable) {
        return pageRepository.search(request, pageable);
    }

    @Cacheable(value = WallRideCacheConfiguration.PAGE_CACHE)
    public List<Page> getPathPages(Page page) {
        return getPathPages(page, false);
    }

    @Cacheable(value = WallRideCacheConfiguration.PAGE_CACHE)
    public List<Page> getPathPages(Page page, boolean includeUnpublished) {
        return pageRepository.findAll(PageSpecifications.path(page, includeUnpublished));
    }

    public List<Page> getChildPages(Page page) {
        return getChildPages(page, false);
    }

    public List<Page> getChildPages(Page page, boolean includeUnpublished) {
        return pageRepository.findAll(PageSpecifications.children(page, includeUnpublished));
    }

    public List<Page> getSiblingPages(Page page) {
        return getSiblingPages(page, false);
    }

    public List<Page> getSiblingPages(Page page, boolean includeUnpublished) {
        return pageRepository.findAll(PageSpecifications.siblings(page, includeUnpublished));
    }

    public Page getPageById(long id) {
        return pageRepository.findOneById(id);
    }

    public Page getPageById(long id, String language) {
        return pageRepository.findOneByIdAndLanguage(id, language);
    }

    @Cacheable(value = WallRideCacheConfiguration.PAGE_CACHE)
    public Page getPageByCode(String code, String language) {
        return pageRepository.findOneByCodeAndLanguage(code, language);
    }

    public Page getDraftById(long id) {
        return pageRepository.findOne(PageSpecifications.draft(entityManager.getReference(Page.class, id)));
    }

    public long countPages(String language) {
        return pageRepository.count(language);
    }

    public long countPagesByStatus(Post.Status status, String language) {
        return pageRepository.countByStatus(status, language);
    }
}