News.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.quickinfo.model;
import org.silverpeas.components.delegatednews.model.DelegatedNews;
import org.silverpeas.core.ResourceReference;
import org.silverpeas.core.comment.service.CommentService;
import org.silverpeas.core.comment.service.CommentServiceProvider;
import org.silverpeas.core.contribution.ContributionVisibility;
import org.silverpeas.core.contribution.attachment.AttachmentServiceProvider;
import org.silverpeas.core.contribution.attachment.model.DocumentType;
import org.silverpeas.core.contribution.attachment.model.SimpleDocument;
import org.silverpeas.core.contribution.model.ContributionIdentifier;
import org.silverpeas.core.contribution.model.ContributionModel;
import org.silverpeas.core.contribution.model.SilverpeasContent;
import org.silverpeas.core.contribution.model.Thumbnail;
import org.silverpeas.core.contribution.model.WithAttachment;
import org.silverpeas.core.contribution.model.WithPermanentLink;
import org.silverpeas.core.contribution.model.WithThumbnail;
import org.silverpeas.core.contribution.publication.model.PublicationDetail;
import org.silverpeas.core.contribution.publication.model.PublicationPK;
import org.silverpeas.core.contribution.publication.model.PublicationPath;
import org.silverpeas.core.date.Period;
import org.silverpeas.core.i18n.I18NHelper;
import org.silverpeas.core.io.media.image.thumbnail.control.ThumbnailController;
import org.silverpeas.core.io.media.image.thumbnail.model.ThumbnailDetail;
import org.silverpeas.core.pdc.pdc.model.ClassifyPosition;
import org.silverpeas.core.pdc.pdc.model.PdcException;
import org.silverpeas.core.pdc.pdc.service.PdcManager;
import org.silverpeas.core.persistence.datasource.model.identifier.UuidIdentifier;
import org.silverpeas.core.persistence.datasource.model.jpa.SilverpeasJpaEntity;
import org.silverpeas.core.reminder.WithReminder;
import org.silverpeas.core.silverstatistics.access.service.StatisticService;
import org.silverpeas.core.util.DateUtil;
import org.silverpeas.kernel.util.StringUtil;
import org.silverpeas.core.util.URLUtil;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import static org.silverpeas.core.date.TemporalConverter.asDate;
import static org.silverpeas.core.date.TemporalConverter.asOffsetDateTime;
@Entity
@Table(name = "sc_quickinfo_news")
@NamedQuery(name = "newsFromComponentInstances", query = "select n from News n where n" +
".componentInstanceId in :componentInstanceIds order by n.publishDate DESC" +
", n.lastUpdateDate DESC")
@NamedQuery(name = "newsByForeignId", query = "select n from News n where n.publicationId = " +
":foreignId")
@NamedQuery(name = "newsMandatories", query = "select n from News n where n.mandatory = " +
":mandatory")
@NamedQuery(name = "newsForTicker", query = "select n from News n where n.ticker = :ticker")
public class News extends SilverpeasJpaEntity<News, UuidIdentifier> implements SilverpeasContent,
WithAttachment, WithThumbnail, WithReminder, WithPermanentLink {
public static final String CONTRIBUTION_TYPE = "News";
private static final long serialVersionUID = 1L;
@Transient private PublicationDetail publication;
@Transient
private String content;
@Transient
private DelegatedNews delegatedNews;
@Column(name = "instanceId", nullable = false)
private String componentInstanceId;
@Column(name = "important", nullable = false)
@NotNull
private boolean important = false;
@Column(name = "broadcastTicker", nullable = false)
@NotNull
private boolean ticker = false;
@Column(name = "broadcastMandatory", nullable = false)
@NotNull
private boolean mandatory = false;
@Column(name = "foreignId", nullable = false)
@Size(min = 1)
private String publicationId;
@Column
private Date publishDate;
@Column
private String publishedBy;
/**
* Gets a builder of {@link News} instances.
* @return a {@link Builder} instance
*/
public static Builder builder() {
return new Builder();
}
/**
* Gets a builder of {@link News} instances from data of another one.
* @param news the news data to initialize with.
* @return a {@link Builder} instance
*/
public static Builder builder(final News news) {
return builder()
.setTitleAndDescription(news.getTitle(), news.getDescription())
.setKeywords(news.getKeywords())
.setVisibilityPeriod(news.getVisibility().getPeriod())
.setImportant(news.isImportant())
.setTicker(news.isTicker())
.setMandatory(news.isMandatory());
}
protected News() {
// default constructor for the persistence engine
super();
}
public NewsPK getPK() {
return new NewsPK(getId(), getComponentInstanceId());
}
public News(PublicationDetail publication) {
setPublication(publication);
}
public PublicationDetail getPublication() {
return publication;
}
@Override
public News setId(String id) {
return super.setId(id);
}
@Override
public String getTitle() {
return getPublication().getName();
}
public void setTitle(String title) {
getPublication().setName(title);
}
@Override
public String getDescription() {
return getPublication().getDescription();
}
public void setKeywords(String keywords) {
getPublication().setKeywords(keywords);
}
public String getKeywords() {
return getPublication().getKeywords();
}
public void setDescription(String desc) {
getPublication().setDescription(desc);
}
public void setCreatorId(String userId) {
super.createdBy(userId);
getPublication().setCreatorId(userId);
}
public void setUpdaterId(String userId) {
super.lastUpdatedBy(userId);
getPublication().setUpdaterId(userId);
}
public String getUpdaterId() {
return getPublication().getUpdaterId();
}
public Date getUpdateDate() {
return getPublication().getLastUpdateDate();
}
public boolean isVisible() {
return getVisibility().isActive();
}
public boolean isNoMoreVisible() {
return getVisibility().hasBeenActive();
}
public boolean isNotYetVisible() {
return getVisibility().willBeActive();
}
public void setVisibilityPeriod(Period period) {
getPublication().setVisibilityPeriod(period);
}
public ContributionVisibility getVisibility() {
return publication.getVisibility();
}
public void setContentToStore(String content) {
this.content = content;
}
public String getContentToStore() {
return content;
}
public String getContent() {
return getPublication().getContent().getRenderer().renderView();
}
public List<Integer> getBroadcastModes() {
List<Integer> modes = new ArrayList<>();
modes.add(getPublication().getImportance());
return modes;
}
@Override
public Thumbnail getThumbnail() {
ThumbnailDetail thumbnail =
new ThumbnailDetail(getComponentInstanceId(), Integer.parseInt(getPublicationId()),
ThumbnailDetail.THUMBNAIL_OBJECTTYPE_PUBLICATION_VIGNETTE);
return ThumbnailController.getCompleteThumbnail(thumbnail);
}
public int getNumberOfComments() {
CommentService commentService = CommentServiceProvider.getCommentService();
return commentService.getCommentsCountOnResource(CONTRIBUTION_TYPE,
new ResourceReference(getPK()));
}
/**
* Gets the identifier of the component instance which the news is attached.
* @return the identifier of the component instance which the news is attached.
*/
public String getComponentInstanceId() {
return componentInstanceId;
}
public void setComponentInstanceId(String componentId) {
getPublication().getPK().setComponentName(componentId);
this.componentInstanceId = componentId;
}
@Override
public String getSilverpeasContentId() {
return getPublication().getSilverObjectId();
}
@Override
public ContributionIdentifier getIdentifier() {
return ContributionIdentifier.from(getComponentInstanceId(), getId(), getContributionType());
}
@Override
public String getContributionType() {
return CONTRIBUTION_TYPE;
}
@Override
public boolean isIndexable() {
return false;
}
/**
* The type of this resource
*
* @return the same value returned by getContributionType()
*/
public static String getResourceType() {
return CONTRIBUTION_TYPE;
}
@SuppressWarnings("unchecked")
@Override
public Optional<PublicationPath> getResourcePath() {
return getPublication().getResourcePath();
}
public void setImportant(boolean important) {
this.important = important;
}
public boolean isImportant() {
return important;
}
public void setTicker(boolean ticker) {
this.ticker = ticker;
}
public boolean isTicker() {
return ticker;
}
public void setMandatory(boolean mandatory) {
this.mandatory = mandatory;
}
public boolean isMandatory() {
return mandatory;
}
public void setPublicationId(String publicationId) {
this.publicationId = publicationId;
}
public String getPublicationId() {
return publicationId;
}
public int getNbAccess() {
return getStatisticService().getCount(this);
}
public boolean isDraft() {
return getPublication().isDraft();
}
public void setDraft() {
getPublication().setStatus(PublicationDetail.DRAFT_STATUS);
}
public void setPublished() {
getPublication().setStatus(PublicationDetail.VALID_STATUS);
}
public List<ClassifyPosition> getTaxonomyPositions() throws PdcException {
String silverObjectId = getPublication().getSilverObjectId();
if (StringUtil.isDefined(silverObjectId)) {
return getTaxonomyService()
.getPositions(Integer.parseInt(silverObjectId), getComponentInstanceId());
}
return Collections.emptyList();
}
@Override
public String getPermalink() {
return URLUtil.getSimpleURL(URLUtil.URL_PUBLI, getPublicationId());
}
public void setPublishDate(Date publishDate) {
this.publishDate = publishDate;
}
public Date getPublishDate() {
return publishDate;
}
public void setPublishedBy(String publishedBy) {
this.publishedBy = publishedBy;
}
public String getPublishedBy() {
return publishedBy;
}
public boolean isUpdatedAfterBePublished() {
if (getPublishDate() == null) {
return false;
}
return DateUtil.compareTo(getUpdateDate(), getPublishDate(), false) > 0;
}
public DelegatedNews getDelegatedNews() {
return delegatedNews;
}
public void setDelegatedNews(DelegatedNews dn) {
this.delegatedNews = dn;
}
public boolean isCanBeSubmittedOnHomepage() {
return delegatedNews == null || delegatedNews.isDenied();
}
public Date getOnlineDate() {
if (getPublishDate() != null) {
final Date visibilityStart = asDate(asOffsetDateTime(getPublication().getVisibility().getPeriod().getStartDate())
.atZoneSameInstant(ZoneId.systemDefault()));
if (visibilityStart.after(getPublishDate())) {
return visibilityStart;
}
}
return getPublishDate();
}
public int getNumberOfAttachments() {
List<SimpleDocument> attachments = AttachmentServiceProvider.getAttachmentService().
listDocumentsByForeignKeyAndType(getForeignPK().toResourceReference(), DocumentType.attachment,
I18NHelper.DEFAULT_LANGUAGE);
return attachments.size();
}
protected void setPublication(PublicationDetail publication) {
this.publication = publication;
}
protected PublicationPK getForeignPK() {
return new PublicationPK(getPublicationId(), getComponentInstanceId());
}
private StatisticService getStatisticService() {
return StatisticService.get();
}
private PdcManager getTaxonomyService() {
return PdcManager.get();
}
@Override
public int hashCode() {
return super.hashCode();
}
@Override
public boolean equals(final Object obj) {
return super.equals(obj);
}
@Override
public ContributionModel getModel() {
return new NewsModel(this);
}
/**
* A builder of a {@link News} instance by setting some of its properties.
*/
public static class Builder {
private final News news = new News();
public Builder() {
news.publication = PublicationDetail.builder().build();
}
/**
* Builds a {@link News} instance from the properties that were previously set with this
* builder.
* @return a {@link News} instance.
*/
public News build() {
return news;
}
/**
* Sets mandatory flag of the {@link News} instance to build.
* @param mandatory the mandatory flag.
* @return itself.
*/
public Builder setMandatory(boolean mandatory) {
news.setMandatory(mandatory);
return this;
}
/**
* Sets ticker flag of the {@link News} instance to build.
* @param ticker the ticker flag.
* @return itself.
*/
public Builder setTicker(boolean ticker) {
news.setTicker(ticker);
return this;
}
/**
* Sets important flag of the {@link News} instance to build.
* @param important the important flag.
* @return itself.
*/
public Builder setImportant(boolean important) {
news.setImportant(important);
return this;
}
/**
* Sets the visibility period of the {@link News} instance to build.
* @param period the visibility period.
* @return itself.
*/
public Builder setVisibilityPeriod(Period period) {
news.setVisibilityPeriod(period);
return this;
}
/**
* Sets the keywords of the {@link News} instance to build.
* @param keywords the keywords of the news.
* @return itself.
*/
public Builder setKeywords(final String keywords) {
news.setKeywords(keywords);
return this;
}
/**
* Sets the given title and description of the news to build.
* @param title the title of the news.
* @param description the description of the news.
* @return itself.
*/
public Builder setTitleAndDescription(final String title, final String description) {
news.setTitle(title);
news.setDescription(description);
return this;
}
}
}