001/* 002 * Copyright 2010 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 */ 016 017package org.ametys.cms.repository.comment; 018 019import java.time.ZonedDateTime; 020import java.util.Collection; 021import java.util.List; 022import java.util.Optional; 023import java.util.function.BiFunction; 024 025import org.apache.commons.lang3.StringUtils; 026 027import org.ametys.cms.repository.CommentableAmetysObject; 028import org.ametys.cms.repository.mentions.MentionUtils; 029import org.ametys.core.user.UserIdentity; 030import org.ametys.plugins.repository.AmetysRepositoryException; 031import org.ametys.plugins.repository.data.holder.ModifiableDataHolder; 032 033/** 034 * A comment on a {@link CommentableAmetysObject} 035 */ 036public class Comment extends AbstractComment 037{ 038 039 /** 040 * Retrieves a comment by its id 041 * @param rootDataHolder The root data holder hosting the first level of comments 042 * @param commentId The id of the comment to retrieve 043 * @throws AmetysRepositoryException if an error occurred 044 */ 045 public Comment(ModifiableDataHolder rootDataHolder, String commentId) 046 { 047 super(rootDataHolder, commentId); 048 } 049 050 /** 051 * Creates a new comment 052 * @param dataHolder The data holder where to add the new comment 053 */ 054 public Comment(ModifiableDataHolder dataHolder) 055 { 056 super(dataHolder, Optional.empty(), Optional.empty()); 057 } 058 059 /** 060 * Creates a new comment, with the given id and creation date 061 * This method allows to create a comment from existing data (ex: data import from archive) 062 * The id is not generated here, the source is trusted. Be careful using this method 063 * @param dataHolder The data holder where to add the new comment 064 * @param commentId the comment's id 065 * @param creationDate the comment's creation date 066 */ 067 public Comment(ModifiableDataHolder dataHolder, String commentId, ZonedDateTime creationDate) 068 { 069 super(dataHolder, Optional.ofNullable(commentId), Optional.ofNullable(creationDate)); 070 } 071 072 private Comment(ModifiableDataHolder dataHolder, Optional<String> commentId, Optional<ZonedDateTime> creationDate) 073 { 074 super(dataHolder, commentId, creationDate); 075 } 076 077 /** 078 * Creates a new sub comment of the comment 079 * @param comment The parent comment 080 */ 081 public Comment(Comment comment) 082 { 083 this(comment, Optional.empty(), Optional.empty()); 084 } 085 086 /** 087 * Creates a new sub comment of the comment, with the given id and creation date 088 * This method allow to create a sub comment from existing data (ex: data import from archive) 089 * The id is not generated here, the source is trusted. Be careful using this method 090 * @param comment The parent comment 091 * @param commentId the sub comment's id 092 * @param creationDate the sub comment's creation date 093 */ 094 public Comment(Comment comment, String commentId, ZonedDateTime creationDate) 095 { 096 this(comment, Optional.ofNullable(commentId), Optional.ofNullable(creationDate)); 097 } 098 099 private Comment(Comment comment, Optional<String> commentId, Optional<ZonedDateTime> creationDate) 100 { 101 super(comment, commentId, creationDate); 102 } 103 104 /** 105 * Creates a reference comment of the comment, with the given comment 106 * @param parentComment The parent comment 107 * @param refComment the referenced comment 108 */ 109 public Comment(Comment parentComment, AbstractComment refComment) 110 { 111 super(parentComment, refComment); 112 } 113 114 /** 115 * Get a comment 116 * @param rootDataHolder The root data holder of the first level of comments 117 * @param commentId The comment identifier 118 * @return The comment 119 * @throws AmetysRepositoryException if the comment does not exist 120 */ 121 public static Comment getComment(ModifiableDataHolder rootDataHolder, String commentId) throws AmetysRepositoryException 122 { 123 return new Comment(rootDataHolder, commentId); 124 } 125 126 /** 127 * Get the sub comments of the given comment 128 * @param parentComment The parent comment 129 * @param includeNotValidatedComments True to include the comments that are not validated 130 * @param includeValidatedComments True to include the comments that are validated 131 * @return the list of sub comments 132 * @throws AmetysRepositoryException If an error occurred 133 */ 134 public static List<Comment> getComments(Comment parentComment, boolean includeNotValidatedComments, boolean includeValidatedComments) throws AmetysRepositoryException 135 { 136 return getComments(parentComment, includeNotValidatedComments, includeValidatedComments, false); 137 } 138 139 /** 140 * Get the sub comments of the given comment 141 * @param parentComment The parent comment 142 * @param includeNotValidatedComments True to include the comments that are not validated 143 * @param includeValidatedComments True to include the comments that are validated 144 * @param withSubComment true if we want to get all child comments 145 * @return the list of comments 146 * @throws AmetysRepositoryException If an error occurred 147 */ 148 public static List<Comment> getComments(Comment parentComment, boolean includeNotValidatedComments, boolean includeValidatedComments, boolean withSubComment) throws AmetysRepositoryException 149 { 150 return getComments(parentComment, includeNotValidatedComments, includeValidatedComments, withSubComment, getCreationFunction()); 151 } 152 153 /** 154 * Get the comments in the given root data holder 155 * @param rootDataHolder The root data holder 156 * @param includeNotValidatedComments True to include the comments that are not validated 157 * @param includeValidatedComments True to include the comments that are validated 158 * @return the list of comments 159 * @throws AmetysRepositoryException If an error occurred 160 */ 161 public static List<Comment> getComments(ModifiableDataHolder rootDataHolder, boolean includeNotValidatedComments, boolean includeValidatedComments) throws AmetysRepositoryException 162 { 163 return getComments(rootDataHolder, includeNotValidatedComments, includeValidatedComments, false); 164 } 165 166 /** 167 * Get the comments in the given root data holder 168 * @param rootDataHolder The root data holder 169 * @param includeNotValidatedComments True to include the comments that are not validated 170 * @param includeValidatedComments True to include the comments that are validated 171 * @param isRecursive true if we want to have sub comments 172 * @return the list of comments 173 * @throws AmetysRepositoryException If an error occurred 174 */ 175 //public static <T extends AbstractComment> List<T> getComments(ModifiableDataHolder rootDataHolder, boolean includeNotValidatedComments, boolean includeValidatedComments, boolean isRecursive, BiFunction<ModifiableDataHolder, String, T> commentCreator) throws AmetysRepositoryException 176 public static List<Comment> getComments(ModifiableDataHolder rootDataHolder, boolean includeNotValidatedComments, boolean includeValidatedComments, boolean isRecursive) throws AmetysRepositoryException 177 { 178 return getComments(rootDataHolder, includeNotValidatedComments, includeValidatedComments, isRecursive, getCreationFunction()); 179 } 180 181 @Override 182 protected void update() 183 { 184 long validated = 0; 185 long notValidated = 0; 186 187 ModifiableDataHolder dataHolder = _rootDataHolder; 188 if (isSubComment()) 189 { 190 dataHolder = getCommentParent()._rootDataHolder; 191 } 192 193 List<Comment> comments = getComments(dataHolder, true, true, false, getCreationFunction()); 194 195 for (AbstractComment comment : comments) 196 { 197 if (comment.isValidated()) 198 { 199 validated++; 200 } 201 else 202 { 203 notValidated++; 204 } 205 } 206 207 dataHolder.setValue(METADATA_COMMENTS_VALIDATED, validated); 208 dataHolder.setValue(METADATA_COMMENTS_NOTVALIDATED, notValidated); 209 } 210 211 @SuppressWarnings("unchecked") 212 @Override 213 public Comment getCommentParent() 214 { 215 if (isSubComment()) 216 { 217 String parentId = StringUtils.substringBeforeLast(this.getId(), ID_SEPARATOR); 218 return getComment(_rootDataHolder, parentId); 219 } 220 return null; 221 } 222 223 @SuppressWarnings("unchecked") 224 @Override 225 public List<Comment> getSubComment(boolean includeNotValidatedComments, boolean includeValidatedComments) 226 { 227 return getComments(this, includeNotValidatedComments, includeValidatedComments); 228 } 229 230 @SuppressWarnings("unchecked") 231 @Override 232 public Comment getReferencedComment() 233 { 234 return getReferencedComment(this, getCreationFunction()); 235 } 236 237 /** 238 * Create sub comment from this comment 239 * 240 * @return the sub comment 241 */ 242 @SuppressWarnings("unchecked") 243 @Override 244 public Comment createSubComment() 245 { 246 return new Comment(this); 247 } 248 249 @SuppressWarnings("unchecked") 250 @Override 251 public Comment createSubComment(String commentId, ZonedDateTime creationDate) 252 { 253 return new Comment(this, commentId, creationDate); 254 } 255 256 @SuppressWarnings("unchecked") 257 @Override 258 public Comment createReferencedComment(AbstractComment comment) 259 { 260 return new Comment(this, comment); 261 } 262 263 private static BiFunction<ModifiableDataHolder, String, Comment> getCreationFunction() 264 { 265 return (dataHolder, name) -> 266 { 267 Comment comment = new Comment(dataHolder, name); 268 return comment; 269 }; 270 } 271 272 /** 273 * Extract users mentioned in the comment 274 * @return the mentioned users 275 */ 276 public Collection<UserIdentity> extractMentions() 277 { 278 String content = getContent(); 279 280 return MentionUtils.extractMentionedUsersFromSimpleText(content); 281 } 282}