# DelegatedNews.java

    /*
     * Copyright (C) 2000 - 2026 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.model;

    import org.silverpeas.core.contribution.model.ContributionIdentifier;
    import org.silverpeas.core.contribution.publication.model.PublicationDetail;
    import org.silverpeas.core.contribution.publication.model.PublicationPK;
    import org.silverpeas.core.contribution.publication.model.PublicationRuntimeException;
    import org.silverpeas.core.contribution.publication.service.PublicationService;
    import org.silverpeas.core.date.Period;
    import org.silverpeas.core.persistence.datasource.model.identifier.ExternalIntegerIdentifier;
    import org.silverpeas.core.persistence.datasource.model.jpa.BasicJpaEntity;

    import jakarta.persistence.*;
    import java.io.Serializable;
    import java.time.ZoneId;
    import java.util.Date;
    import java.util.Objects;
    import java.util.Optional;

    import static org.silverpeas.core.date.TemporalConverter.asDate;
    import static org.silverpeas.core.date.TemporalConverter.asOffsetDateTime;

    @Entity
    @Table(name = "sc_delegatednews_news")
    @AttributeOverride(name = "id", column = @Column(name = "pubId", columnDefinition = "int"))
    @NamedQuery(name = "delegatednews.findByStatus", query = "SELECT dn FROM DelegatedNews dn " +
        "WHERE dn.status = :status " +
        "AND (" + "(dn.beginDate is null AND dn.endDate is null) " +
        "OR " +
        "(dn.beginDate is null AND dn.endDate is not null AND CURRENT_TIMESTAMP <= dn.endDate) " +
        "OR " +
        "(dn.beginDate is not null AND dn.endDate is null AND CURRENT_TIMESTAMP >= dn.beginDate) " +
        "OR " +
        "(dn.beginDate is not null AND dn.endDate is not null AND CURRENT_TIMESTAMP >= dn" +
        ".beginDate AND CURRENT_TIMESTAMP <= dn.endDate) " + ")" + "ORDER BY dn.newsOrder ASC")
    @NamedQuery(name = "delegatednews.findAllOrderedNews", query =
        "SELECT dn FROM DelegatedNews dn " +
            "ORDER BY dn.newsOrder ASC, dn.beginDate ASC, dn.id.id ASC")
    public class DelegatedNews extends BasicJpaEntity<DelegatedNews, ExternalIntegerIdentifier>
        implements Serializable {

      private static final long serialVersionUID = 9192830552642027995L;

      @Column(name = "instanceId")
      private String instanceId;
      @Column(name = "status")
      private String status;
      @Column(name = "contributorId")
      private String contributorId;
      @Column(name = "validatorId")
      private String validatorId;
      @Column(name = "validationDate", columnDefinition = "TIMESTAMP")
      private Date validationDate;
      @Column(name = "beginDate", columnDefinition = "TIMESTAMP")
      private Date beginDate;
      @Column(name = "endDate", columnDefinition = "TIMESTAMP")
      private Date endDate;
      @Column(name = "newsOrder")
      private int newsOrder = 0;

      public static final String NEWS_TO_VALIDATE = "ToValidate";
      public static final String NEWS_VALID = "Valid";
      public static final String NEWS_REFUSED = "Refused";

      public DelegatedNews() {

      }

      public DelegatedNews(ContributionIdentifier contributionId, final String contributorId,
          Date validationDate, Period visibilityPeriod) {
        super();
        setId(contributionId.getLocalId());
        this.instanceId = contributionId.getComponentInstanceId();
        this.status = NEWS_TO_VALIDATE;
        this.contributorId = contributorId;
        if (validationDate != null) {
          this.validationDate = new Date(validationDate.getTime());
        }
        setVisibilityPeriod(visibilityPeriod);
      }

      public String getPubId() {
        return getId();
      }

      public void setPubId(int pubId) {
        setId(Integer.toString(pubId));
      }

      public String getInstanceId() {
        return instanceId;
      }

      public void setInstanceId(String instanceId) {
        this.instanceId = instanceId;
      }

      public String getStatus() {
        return status;
      }

      public void setStatus(String status) {
        this.status = status;
      }

      public String getContributorId() {
        return contributorId;
      }

      public void setContributorId(String contributorId) {
        this.contributorId = contributorId;
      }

      public String getValidatorId() {
        return validatorId;
      }

      public void setValidatorId(String validatorId) {
        this.validatorId = validatorId;
      }

      public Date getValidationDate() {
        return validationDate;
      }

      public void setValidationDate(Date validationDate) {
        this.validationDate = validationDate;
      }

      public Date getBeginDate() {
        return beginDate;
      }

      public Date getEndDate() {
        return endDate;
      }

      public final void setVisibilityPeriod(final Period visibilityPeriod) {
        final Optional<Period> specificPeriod = Optional.ofNullable(visibilityPeriod);
        this.beginDate = specificPeriod
            .filter(p -> !p.startsAtMinDate())
            .map(p -> asDate(asOffsetDateTime(p.getStartDate()).atZoneSameInstant(ZoneId.systemDefault())))
            .orElse(null);
        this.endDate = specificPeriod
            .filter(p -> !p.endsAtMaxDate())
            .map(p -> asDate(asOffsetDateTime(p.getEndDate()).atZoneSameInstant(ZoneId.systemDefault())))
            .orElse(null);
      }

      public int getNewsOrder() {
        return newsOrder;
      }

      public void setNewsOrder(int newsOrder) {
        this.newsOrder = newsOrder;
      }

      public boolean isValidated() {
        return DelegatedNews.NEWS_VALID.equals(getStatus());
      }

      public boolean isDenied() {
        return DelegatedNews.NEWS_REFUSED.equals(getStatus());
      }

      public boolean isWaitingForValidation() {
        return DelegatedNews.NEWS_TO_VALIDATE.equals(getStatus());
      }

      public PublicationDetail getPublicationDetail() {
        try {
          PublicationService publicationService = PublicationService.get();
          PublicationPK pubPk = new PublicationPK(getId(), this.instanceId);
          return publicationService.getDetail(pubPk);
        } catch (Exception e) {
          throw new PublicationRuntimeException(e);
        }
      }

      @Override
      public boolean equals(Object obj) {
        if (obj == null) {
          return false;
        }
        if (getClass() != obj.getClass()) {
          return false;
        }
        final DelegatedNews other = (DelegatedNews) obj;
        if (!this.getPubId().equals(other.getPubId())) {
          return false;
        }
        if (!Objects.equals(this.instanceId, other.instanceId)) {
          return false;
        }
        if (!Objects.equals(this.status, other.status)) {
          return false;
        }
        if (!Objects.equals(this.contributorId, other.contributorId)) {
          return false;
        }
        if (!Objects.equals(this.validatorId, other.validatorId)) {
          return false;
        }
        if (!Objects.equals(this.validationDate, other.validationDate)) {
          return false;
        }
        if (!Objects.equals(this.beginDate, other.beginDate)) {
          return false;
        }
        if (!Objects.equals(this.endDate, other.endDate)) {
          return false;
        }
        return this.newsOrder == -1 ? other.newsOrder == -1 : this.newsOrder == other.newsOrder;
      }

      @Override
      public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + Integer.parseInt(getPubId());
        result = prime * result + ((instanceId == null) ? 0 : instanceId.hashCode());
        result = prime * result + ((status == null) ? 0 : status.hashCode());
        result = prime * result + ((contributorId == null) ? 0 : contributorId.hashCode());
        result = prime * result + ((validatorId == null) ? 0 : validatorId.hashCode());
        result = prime * result + ((validationDate == null) ? 0 : validationDate.hashCode());
        result = prime * result + ((beginDate == null) ? 0 : beginDate.hashCode());
        result = prime * result + ((endDate == null) ? 0 : endDate.hashCode());
        result = prime * result + newsOrder;
        return result;
      }

      @Override
      public String toString() {
        return "DelegatedNews {" + "pubId=" + getPubId() + ", instanceId=" + instanceId + ", status=" +
            status + ", contributorId=" + contributorId + ", validatorId=" + validatorId +
            ", validationDate=" + validationDate + ", beginDate=" + beginDate +
            ", endDate=" + endDate + ", newsOrder=" + newsOrder + '}';
      }

    }