001/* 002 * Copyright 2024 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.cms.repository.comment; 017 018import java.time.ZonedDateTime; 019import java.util.List; 020import java.util.Optional; 021import java.util.function.BiFunction; 022 023import org.apache.commons.lang3.StringUtils; 024 025import org.ametys.cms.data.RichText; 026import org.ametys.cms.repository.CommentableAmetysObject; 027import org.ametys.plugins.repository.AmetysRepositoryException; 028import org.ametys.plugins.repository.data.holder.ModifiableModelLessDataHolder; 029 030/** 031 * A comment on a {@link CommentableAmetysObject} with rich text content 032 */ 033public class RichTextComment extends AbstractComment 034{ 035 036 /** Constants for the content Metadata */ 037 public static final String METADATA_RICHTEXT_COMMENT_CONTENT = "richtextcontent"; 038 039 /** Attribute Description for editing */ 040 public static final String ATTRIBUTE_CONTENT_FOR_EDITING = "contentEditing"; 041 /** Attribute Description for editing */ 042 public static final String ATTRIBUTE_CONTENT_FOR_RENDERING = "contentRendering"; 043 /** Attribute Description abstract */ 044 public static final String ATTRIBUTE_CONTENT_ABSTRACT = "contentAbstract"; 045 046 /** 047 * Retrieves a comment by its id 048 * @param contentUnversionedDataHolder The unversioned data holder of the content hosting the comment 049 * @param commentId The id of the comment to retrieve 050 * @throws AmetysRepositoryException if an error occurred 051 */ 052 public RichTextComment(ModifiableModelLessDataHolder contentUnversionedDataHolder, String commentId) 053 { 054 super(contentUnversionedDataHolder, commentId); 055 } 056 057 /** 058 * Creates a new comment on the content 059 * @param contentUnversionedDataHolder The unversioned data holder of the content where to add the new comment 060 */ 061 public RichTextComment(ModifiableModelLessDataHolder contentUnversionedDataHolder) 062 { 063 this(contentUnversionedDataHolder, Optional.empty(), Optional.empty()); 064 } 065 066 /** 067 * Creates a new comment on the content, with the given id and creation date 068 * This method allow to create a comment from existing data (ex: data import from archive) 069 * The id is not generated here, the source is trusted. Be careful using this method 070 * @param contentUnversionedDataHolder The unversioned data holder of the content where to add the new comment 071 * @param commentId the comment's id 072 * @param creationDate the comment's creation date 073 */ 074 public RichTextComment(ModifiableModelLessDataHolder contentUnversionedDataHolder, String commentId, ZonedDateTime creationDate) 075 { 076 this(contentUnversionedDataHolder, Optional.ofNullable(commentId), Optional.ofNullable(creationDate)); 077 } 078 079 private RichTextComment(ModifiableModelLessDataHolder contentUnversionedDataHolder, Optional<String> commentId, Optional<ZonedDateTime> creationDate) 080 { 081 super(contentUnversionedDataHolder, commentId, creationDate); 082 } 083 084 /** 085 * Creates a new sub comment of the comment 086 * @param comment The parent comment 087 */ 088 public RichTextComment(RichTextComment comment) 089 { 090 this(comment, Optional.empty(), Optional.empty()); 091 } 092 093 /** 094 * Creates a new sub comment of the comment, with the given id and creation date 095 * This method allow to create a sub comment from existing data (ex: data import from archive) 096 * The id is not generated here, the source is trusted. Be careful using this method 097 * @param comment The parent comment 098 * @param commentId the sub comment's id 099 * @param creationDate the sub comment's creation date 100 */ 101 public RichTextComment(RichTextComment comment, String commentId, ZonedDateTime creationDate) 102 { 103 this(comment, Optional.ofNullable(commentId), Optional.ofNullable(creationDate)); 104 } 105 106 private RichTextComment(RichTextComment comment, Optional<String> commentId, Optional<ZonedDateTime> creationDate) 107 { 108 super(comment, commentId, creationDate); 109 } 110 111 /** 112 * Get a comment 113 * @param contentUnversionedDataHolder the content data holder 114 * @param commentId The comment identifier 115 * @return The comment 116 * @throws AmetysRepositoryException if the comment does not exist 117 */ 118 public static RichTextComment getComment(ModifiableModelLessDataHolder contentUnversionedDataHolder, String commentId) throws AmetysRepositoryException 119 { 120 return new RichTextComment(contentUnversionedDataHolder, commentId); 121 } 122 123 /** 124 * Get the comments of a content 125 * @param <T> type of the value to retrieve 126 * @param parentComment The parent comment 127 * @param includeNotValidatedComments True to include the comments that are not validated 128 * @param includeValidatedComments True to include the comments that are validated 129 * @return the list of comments 130 * @throws AmetysRepositoryException If an error occurred 131 */ 132 public static <T extends AbstractComment> List<T> getComments(RichTextComment parentComment, boolean includeNotValidatedComments, boolean includeValidatedComments) throws AmetysRepositoryException 133 { 134 return getComments(parentComment, includeNotValidatedComments, includeValidatedComments, false); 135 } 136 137 /** 138 * Get the comments of a content 139 * @param <T> type of the value to retrieve 140 * @param parentComment The parent comment 141 * @param includeNotValidatedComments True to include the comments that are not validated 142 * @param includeValidatedComments True to include the comments that are validated 143 * @param withSubComment true if we want to get all child comments 144 * @return the list of comments 145 * @throws AmetysRepositoryException If an error occurred 146 */ 147 @SuppressWarnings("unchecked") 148 public static <T extends AbstractComment> List<T> getComments(RichTextComment parentComment, boolean includeNotValidatedComments, boolean includeValidatedComments, boolean withSubComment) throws AmetysRepositoryException 149 { 150 return (List<T>) getComments(parentComment, includeNotValidatedComments, includeValidatedComments, withSubComment, getCreationFunction()); 151 } 152 153 /** 154 * Get the comments of a content 155 * @param <T> type of the value to retrieve 156 * @param contentUnversionedDataHolder The content unversioned data holder 157 * @param includeNotValidatedComments True to include the comments that are not validated 158 * @param includeValidatedComments True to include the comments that are validated 159 * @return the list of comments 160 * @throws AmetysRepositoryException If an error occurred 161 */ 162 public static <T extends AbstractComment> List<T> getComments(ModifiableModelLessDataHolder contentUnversionedDataHolder, boolean includeNotValidatedComments, boolean includeValidatedComments) throws AmetysRepositoryException 163 { 164 return getComments(contentUnversionedDataHolder, includeNotValidatedComments, includeValidatedComments, false); 165 } 166 167 /** 168 * Get the comments of a content 169 * @param <T> type of the value to retrieve 170 * @param contentUnversionedDataHolder The content unversioned metadata holder 171 * @param includeNotValidatedComments True to include the comments that are not validated 172 * @param includeValidatedComments True to include the comments that are validated 173 * @param isRecursive true if we want to have sub comments 174 * @return the list of comments 175 * @throws AmetysRepositoryException If an error occurred 176 */ 177 public static <T extends AbstractComment> List<T> getComments(ModifiableModelLessDataHolder contentUnversionedDataHolder, boolean includeNotValidatedComments, boolean includeValidatedComments, boolean isRecursive) throws AmetysRepositoryException 178 { 179 return getComments(contentUnversionedDataHolder, includeNotValidatedComments, includeValidatedComments, isRecursive, getCreationFunction()); 180 } 181 182 @Override 183 protected void update() 184 { 185 long validated = 0; 186 long notValidated = 0; 187 188 ModifiableModelLessDataHolder dataHolder = _rootDataHolder; 189 if (isSubComment()) 190 { 191 dataHolder = getCommentParent()._rootDataHolder; 192 } 193 194 List<RichTextComment> comments = getComments(dataHolder, true, true, false, getCreationFunction()); 195 196 for (AbstractComment comment : comments) 197 { 198 if (comment.isValidated()) 199 { 200 validated++; 201 } 202 else 203 { 204 notValidated++; 205 } 206 } 207 208 dataHolder.setValue(METADATA_COMMENTS_VALIDATED, validated); 209 dataHolder.setValue(METADATA_COMMENTS_NOTVALIDATED, notValidated); 210 } 211 212 @SuppressWarnings("unchecked") 213 @Override 214 public RichTextComment getCommentParent() 215 { 216 if (isSubComment()) 217 { 218 String parentId = StringUtils.substringBeforeLast(this.getId(), ID_SEPARATOR); 219 return new RichTextComment(_rootDataHolder, parentId); 220 } 221 return null; 222 } 223 224 @SuppressWarnings("unchecked") 225 @Override 226 public List<RichTextComment> getSubComment(boolean includeNotValidatedComments, boolean includeValidatedComments) 227 { 228 return getComments(this, includeNotValidatedComments, includeValidatedComments); 229 } 230 231 /** 232 * Create sub comment from this comment 233 * @return the sub comment 234 */ 235 @SuppressWarnings("unchecked") 236 @Override 237 public <T extends AbstractComment> T createSubComment() 238 { 239 return (T) new RichTextComment(this); 240 } 241 242 @SuppressWarnings("unchecked") 243 @Override 244 public <T extends AbstractComment> T createSubComment(String commentId, ZonedDateTime creationDate) 245 { 246 return (T) new RichTextComment(this, commentId, creationDate); 247 } 248 249 250 @SuppressWarnings("unchecked") 251 private static <T extends AbstractComment> BiFunction<ModifiableModelLessDataHolder, String, T> getCreationFunction() 252 { 253 return (dataHolder, name) -> { 254 RichTextComment comment = new RichTextComment(dataHolder, name); 255 return (T) comment; 256 }; 257 } 258 259 /** 260 * Set rich text comment 261 * @param richText the content of the comment 262 */ 263 public void setRichTextContent(RichText richText) 264 { 265 _commentComposite.setValue(METADATA_RICHTEXT_COMMENT_CONTENT, richText, org.ametys.cms.data.type.ModelItemTypeConstants.RICH_TEXT_ELEMENT_TYPE_ID); 266 } 267 268 /** 269 * Get the rich text content 270 * @return rich text content 271 */ 272 public RichText getRichTextContent() 273 { 274 return _commentComposite.getValueOfType(METADATA_RICHTEXT_COMMENT_CONTENT, org.ametys.cms.data.type.ModelItemTypeConstants.RICH_TEXT_ELEMENT_TYPE_ID); 275 } 276 277 /** 278 * Check if there is a rich text content 279 * @return true if there is a rich text content 280 */ 281 public boolean hasRichTextContent() 282 { 283 return _commentComposite.hasValue(METADATA_RICHTEXT_COMMENT_CONTENT); 284 } 285 286}