am.ik.categolj2.domain.service.entry.EntryServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for am.ik.categolj2.domain.service.entry.EntryServiceImpl.java

Source

/*
 * Copyright (C) 2014 Toshiaki Maki
 *
 * 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 am.ik.categolj2.domain.service.entry;

import am.ik.categolj2.core.message.MessageKeys;
import am.ik.categolj2.domain.model.Category;
import am.ik.categolj2.domain.model.Entry;
import am.ik.categolj2.domain.model.EntryHistory;
import am.ik.categolj2.domain.model.Tag;
import am.ik.categolj2.domain.repository.category.CategoryRepository;
import am.ik.categolj2.domain.repository.entry.EntryHistoryRepository;
import am.ik.categolj2.domain.repository.entry.EntryRepository;
import am.ik.categolj2.domain.repository.tag.TagAndEntryId;
import am.ik.categolj2.domain.repository.tag.TagRepository;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.collect.TreeMultimap;
import lombok.extern.slf4j.Slf4j;
import org.dozer.Mapper;
import org.joda.time.DateTime;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
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.annotation.Transactional;
import org.springframework.util.Assert;
import org.terasoluna.gfw.common.date.DateFactory;
import org.terasoluna.gfw.common.exception.ResourceNotFoundException;
import org.terasoluna.gfw.common.message.ResultMessages;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

@Service
@Slf4j
public class EntryServiceImpl implements EntryService {
    @Inject
    EntryRepository entryRepository;
    @Inject
    EntryHistoryRepository entryHistoryRepository;
    @Inject
    CategoryRepository categoryRepository;
    @Inject
    TagRepository tagRepository;
    @Inject
    Mapper beanMapper;
    @Inject
    DateFactory dateFactory;
    Pageable recentPageable = new PageRequest(0, 10);

    @Override
    public Entry findOne(Integer entryId) {
        Entry entry = entryRepository.findDetails(entryId);
        if (entry == null) {
            ResultMessages messages = ResultMessages.error().add(MessageKeys.E_CT_EN_8201, entryId);
            throw new ResourceNotFoundException(messages);
        }
        return entry;
    }

    @Override
    @Cacheable("entry")
    public Entry findOnePublished(Integer entryId) {
        Entry entry = entryRepository.findDetailsPublished(entryId);
        if (entry == null) {
            ResultMessages messages = ResultMessages.error().add(MessageKeys.E_CT_EN_8201, entryId);
            throw new ResourceNotFoundException(messages);
        }
        return entry;
    }

    @Override
    public Page<Entry> findPage(Pageable pageable) {
        Page<Entry> page = entryRepository.findPageOrderByLastModifiedDateDesc(pageable);
        applyRelations(page);
        return page;
    }

    void applyRelations(Iterable<Entry> entries) {
        List<Integer> entryIds = StreamSupport.stream(entries.spliterator(), false).map(Entry::getEntryId)
                .collect(Collectors.toList());
        if (!entryIds.isEmpty()) {
            // apply categories
            List<Category> categories = categoryRepository.findByEntryIds(entryIds);

            Multimap<Integer, Category> categoryMultimap = TreeMultimap.create();
            for (Category c : categories) {
                categoryMultimap.put(c.getEntry().getId(), c);
            }
            for (Entry entry : entries) {
                entry.setCategory(new ArrayList<>(categoryMultimap.get(entry.getId())));
            }
            // apply tags
            List<TagAndEntryId> tags = tagRepository.findByEntryIds(entryIds);
            Multimap<Integer, Tag> tagMultimap = HashMultimap.create();
            for (TagAndEntryId tag : tags) {
                tagMultimap.put(tag.getEntryId(), tag.getTag());
            }
            for (Entry entry : entries) {
                entry.setTags(new LinkedHashSet<>(tagMultimap.get(entry.getEntryId())));
            }
        }
    }

    @Override
    @Cacheable("entry")
    public Page<Entry> findPagePublished(Pageable pageable) {
        Page<Entry> page = entryRepository.findPagePublishedOrderByLastModifiedDateDesc(pageable);
        applyRelations(page);
        return page;
    }

    @Override
    @Cacheable("recentPost")
    public List<Entry> findAllPublishedUpdatedRecently() {
        List<Entry> entries = entryRepository.findAllPublishedOrderByLastModifiedDateDesc(recentPageable);
        return entries;
    }

    @Override
    public Page<Entry> findPagePublishedByCategoryNameAndCategoryOrder(String categoryName, Integer categoryOrder,
            Pageable pageable) {
        Page<Entry> page = entryRepository.findPageDetailsPublishedByCategoryNameAndOrder(categoryName,
                categoryOrder, pageable);
        applyRelations(page);
        return page;
    }

    @Override
    public Page<Entry> findPagePublishedByCreatedBy(String createdBy, Pageable pageable) {
        Page<Entry> page = entryRepository.findPagePublishedByCreatedBy(createdBy, pageable);
        applyRelations(page);
        return page;
    }

    @Override
    public Page<Entry> findPagePublishedByTagName(String tagName, Pageable pageable) {
        Page<Entry> page = entryRepository
                .findPageByTags_TagNameAndPublishedTrueOrderByLastModifiedDateDesc(tagName, pageable);
        applyRelations(page);
        return page;
    }

    @Override
    public Page<Entry> findPageByTagName(String tagName, Pageable pageable) {
        Page<Entry> page = entryRepository.findPageByTags_TagNameOrderByLastModifiedDateDesc(tagName, pageable);
        applyRelations(page);
        return page;
    }

    @Override
    public Page<Entry> searchPageByKeyword(String keyword, Pageable pageable) {
        Page<Entry> page = entryRepository.searchPageByKeyword(keyword, pageable);
        applyRelations(page);
        return page;
    }

    @Override
    public Page<Entry> searchPagePublishedByKeyword(String keyword, Pageable pageable) {
        Page<Entry> page = entryRepository.searchPagePublishedByKeyword(keyword, pageable);
        applyRelations(page);
        return page;
    }

    @Override
    @Transactional
    @CacheEvict(value = { "recentPost", "entry" }, allEntries = true)
    public Entry create(Entry entry, List<Category> category) {
        Assert.notNull(entry, "entry must not be null");
        Assert.isNull(entry.getCategory(), "entry.category must be null");
        Assert.notNull(category, "category must not be null or empty");
        Assert.notNull(entry.getTags(), "category must not be null");
        // create new tags
        tagRepository.save(entry.getTags().stream().filter(tag -> !tagRepository.exists(tag.getTagName()))
                .collect(Collectors.toList()));
        DateTime now = dateFactory.newDateTime();
        entry.setCreatedDate(now);
        entry.setLastModifiedDate(now);
        // createdBy,lastModifiedBy are set by AuditingEntityListener
        entryRepository.saveAndFlush(entry);
        Integer entryId = entry.getEntryId();
        for (Category c : category) {
            c.getCategoryPK().setEntryId(entryId);
        }
        entry.setCategory(category);
        return entry;
    }

    @Override
    @Transactional
    @CacheEvict(value = { "recentPost", "entry" }, allEntries = true)
    public Entry update(Integer entryId, Entry updatedEntry, boolean updateLastModifiedDate,
            boolean saveInHistory) {
        Assert.notNull(updatedEntry, "entry must not be null");

        Entry entry = findOne(entryId); // old entry

        if (saveInHistory) {
            log.info("save history for entryId={}", entryId);
            EntryHistory history = beanMapper.map(entry, EntryHistory.class);
            history.setEntry(entry);
            entryHistoryRepository.save(history);
        }

        if (updateLastModifiedDate) {
            DateTime now = dateFactory.newDateTime();
            updatedEntry.setLastModifiedDate(now);
        }

        Set<Tag> reduced = Sets.difference(entry.getTags(), updatedEntry.getTags());
        houseKeepTag(reduced);
        // copy new values to entry
        beanMapper.map(updatedEntry, entry);
        entryRepository.save(entry);
        return entry;
    }

    @Override
    @Transactional
    @CacheEvict(value = { "recentPost", "entry" }, allEntries = true)
    public void delete(Integer entryId) {
        Entry entry = findOne(entryId);
        houseKeepTag(entry.getTags());
        entryRepository.delete(entry);
    }

    void houseKeepTag(Set<Tag> tags) {
        tagRepository.delete(tags.stream().filter(tag -> tagRepository.countByTagName(tag.getTagName()) == 1)
                .peek(tag -> log.info("Delete unused tag -> {}", tag)).collect(Collectors.toList()));
    }
}