# DelegatedNewsServiceImpl.java

    /*
     * Copyright (C) 2000 - 2024 Silverpeas
     *
     * This program is free software: you can redistribute it and/or modify
     * it under the terms of the GNU Affero General Public License as
     * published by the Free Software Foundation, either version 3 of the
     * License, or (at your option) any later version.
     *
     * As a special exception to the terms and conditions of version 3.0 of
     * the GPL, you may redistribute this Program in connection with Free/Libre
     * Open Source Software ("FLOSS") applications as described in Silverpeas's
     * FLOSS exception. You should have received a copy of the text describing
     * the FLOSS exception, and it is also available here:
     * "https://www.silverpeas.org/legal/floss_exception.html"
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     * GNU Affero General Public License for more details.
     *
     * You should have received a copy of the GNU Affero General Public License
     * along with this program. If not, see <https://www.gnu.org/licenses/>.
     */
    package org.silverpeas.components.delegatednews.service;

    import org.silverpeas.components.delegatednews.dao.DelegatedNewsRepository;
    import org.silverpeas.components.delegatednews.model.DelegatedNews;
    import org.silverpeas.components.delegatednews.notification.DelegatedNewsDeniedNotification;
    import org.silverpeas.components.delegatednews.notification.DelegatedNewsToValidateNotification;
    import org.silverpeas.components.delegatednews.notification.DelegatedNewsValidationNotification;
    import org.silverpeas.core.admin.component.ComponentInstanceDeletion;
    import org.silverpeas.core.admin.service.OrganizationController;
    import org.silverpeas.core.admin.user.model.User;
    import org.silverpeas.core.annotation.Service;
    import org.silverpeas.core.contribution.model.Contribution;
    import org.silverpeas.core.contribution.model.ContributionIdentifier;
    import org.silverpeas.core.date.Period;
    import org.silverpeas.kernel.logging.SilverLogger;

    import javax.inject.Inject;
    import javax.transaction.Transactional;
    import java.util.Collection;
    import java.util.Date;
    import java.util.List;
    import java.util.stream.Stream;

    import static java.util.Collections.singletonList;
    import static org.silverpeas.core.notification.user.builder.helper.UserNotificationHelper.buildAndSend;

    @Service
    @Transactional
    public class DelegatedNewsServiceImpl implements DelegatedNewsService, ComponentInstanceDeletion {

      @Inject
      private DelegatedNewsRepository dao;
      @Inject
      private OrganizationController organizationController;

      @Override
      public void delete(final String componentInstanceId) {
        dao.deleteByComponentInstanceId(componentInstanceId);
      }

      @Override
      public void submitNews(Contribution contribution, Period visibilityPeriod, String userId) {
        DelegatedNews delegatedNews = new DelegatedNews(contribution.getIdentifier(),
            contribution.getLastUpdater().getId(), new Date(), visibilityPeriod);
        notifyDelegatedNewsToValidate(delegatedNews, userId);
        dao.saveAndFlush(delegatedNews);
      }

      @Override
      public DelegatedNews getDelegatedNews(String contributionId) {
        return dao.getById(contributionId);
      }

      @Override
      public List<DelegatedNews> getDelegatedNews(final Collection<String> contributionIds) {
        return dao.getById(contributionIds);
      }

      @Override
      public List<DelegatedNews> getAllDelegatedNews() {
        return dao.findAllOrderedNews();
      }

      @Override
      public List<DelegatedNews> getAllValidDelegatedNews() {
        return dao.findByStatus(DelegatedNews.NEWS_VALID);
      }

      @Override
      public void validateDelegatedNews(String contributionId, String validatorId) {
        DelegatedNews delegatedNews = dao.getById(contributionId);
        if (delegatedNews != null) {
          delegatedNews.setStatus(DelegatedNews.NEWS_VALID);
          delegatedNews.setValidatorId(validatorId);
          delegatedNews.setValidationDate(new Date());
          dao.saveAndFlush(delegatedNews);

          notifyValidation(delegatedNews, validatorId);
        }
      }

      @Override
      public void refuseDelegatedNews(String contributionId, String validatorId, String refusalMotive) {
        DelegatedNews delegatedNews = dao.getById(contributionId);
        if (delegatedNews != null) {
          delegatedNews.setStatus(DelegatedNews.NEWS_REFUSED);
          delegatedNews.setValidatorId(validatorId);
          delegatedNews.setValidationDate(new Date());
          dao.saveAndFlush(delegatedNews);

          notifyDelegatedNewsRefused(delegatedNews, refusalMotive, validatorId);
        }
      }

      @Override
      public void updateDateDelegatedNews(String contributionId, Period visibilityPeriod) {
        DelegatedNews delegatedNews = dao.getById(contributionId);
        if (delegatedNews != null) {
          delegatedNews.setVisibilityPeriod(visibilityPeriod);
          dao.saveAndFlush(delegatedNews);
        }
      }

      private OrganizationController getOrganisationController() {
        return organizationController;
      }

      private String getAppId() {
        final String componentName = "delegatednews";
        return Stream.of(getOrganisationController().getCompoId(componentName))
            .map(i -> componentName + i)
            .findFirst()
            .orElseGet(() -> {
              SilverLogger.getLogger(this).warn("No instance of 'DelegatedNews' found !");
              return null;
            });
      }

      /**
       * Notify the editorial team about a news to validate.
       */
      private void notifyDelegatedNewsToValidate(DelegatedNews news, String senderId) {
        final String delegatedNewsInstanceId = getAppId();
        if (delegatedNewsInstanceId != null) {
          final String[] editors = getOrganisationController()
              .getUsersIdsByRoleNames(delegatedNewsInstanceId, singletonList("admin"));
          buildAndSend(new DelegatedNewsToValidateNotification(news, User.getById(senderId), editors,
              delegatedNewsInstanceId));
        }
      }

      @Override
      public void updateDelegatedNews(ContributionIdentifier id, String updaterId,
          Period visibilityPeriod) {
        final DelegatedNews delegatedNews = dao.getById(id.getLocalId());
        if (delegatedNews != null) {
          delegatedNews.setInstanceId(id.getComponentInstanceId());
          delegatedNews.setStatus(DelegatedNews.NEWS_TO_VALIDATE);
          delegatedNews.setContributorId(updaterId);
          delegatedNews.setValidatorId(null);
          delegatedNews.setValidationDate(new Date());
          delegatedNews.setVisibilityPeriod(visibilityPeriod);
          dao.saveAndFlush(delegatedNews);
          notifyDelegatedNewsToValidate(delegatedNews, updaterId);
        }
      }

      @Override
      public void deleteDelegatedNews(String contributionId) {
        DelegatedNews delegatedNews = dao.getById(contributionId);
        if (delegatedNews != null) {
          dao.delete(delegatedNews);
        }
      }

      private void notifyValidation(DelegatedNews news, String senderId) {
        String delegatedNewsInstanceId = getAppId();
        // Notification of the last contributor
        if (delegatedNewsInstanceId != null) {
          buildAndSend(new DelegatedNewsValidationNotification(news, User.getById(senderId)));
        }
      }

      private void notifyDelegatedNewsRefused(DelegatedNews news, String refusalMotive, String userId) {
        String delegatedNewsInstanceId = getAppId();
        // Notification of the last contributor
        if (delegatedNewsInstanceId != null) {
          buildAndSend(new DelegatedNewsDeniedNotification(news, User.getById(userId), refusalMotive));
        }
      }

      @Override
      public DelegatedNews updateOrderDelegatedNews(String contributionId, int newsOrder) {
        DelegatedNews delegatedNews = dao.getById(contributionId);
        delegatedNews.setNewsOrder(newsOrder);
        return dao.saveAndFlush(delegatedNews);
      }
    }