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.ModifiableModelLessDataHolder; 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(ModifiableModelLessDataHolder 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(ModifiableModelLessDataHolder 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(ModifiableModelLessDataHolder dataHolder, String commentId, ZonedDateTime creationDate) 068 { 069 super(dataHolder, Optional.ofNullable(commentId), Optional.ofNullable(creationDate)); 070 } 071 072 private Comment(ModifiableModelLessDataHolder 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 * Get a comment 106 * @param rootDataHolder The root data holder of the first level of comments 107 * @param commentId The comment identifier 108 * @return The comment 109 * @throws AmetysRepositoryException if the comment does not exist 110 */ 111 public static Comment getComment(ModifiableModelLessDataHolder rootDataHolder, String commentId) throws AmetysRepositoryException 112 { 113 return new Comment(rootDataHolder, commentId); 114 } 115 116 /** 117 * Get the sub comments of the given comment 118 * @param parentComment The parent comment 119 * @param includeNotValidatedComments True to include the comments that are not validated 120 * @param includeValidatedComments True to include the comments that are validated 121 * @return the list of sub comments 122 * @throws AmetysRepositoryException If an error occurred 123 */ 124 public static List<Comment> getComments(Comment parentComment, boolean includeNotValidatedComments, boolean includeValidatedComments) throws AmetysRepositoryException 125 { 126 return getComments(parentComment, includeNotValidatedComments, includeValidatedComments, false); 127 } 128 129 /** 130 * Get the sub comments of the given comment 131 * @param parentComment The parent comment 132 * @param includeNotValidatedComments True to include the comments that are not validated 133 * @param includeValidatedComments True to include the comments that are validated 134 * @param withSubComment true if we want to get all child comments 135 * @return the list of comments 136 * @throws AmetysRepositoryException If an error occurred 137 */ 138 public static List<Comment> getComments(Comment parentComment, boolean includeNotValidatedComments, boolean includeValidatedComments, boolean withSubComment) throws AmetysRepositoryException 139 { 140 return getComments(parentComment, includeNotValidatedComments, includeValidatedComments, withSubComment, getCreationFunction()); 141 } 142 143 /** 144 * Get the comments in the given root data holder 145 * @param rootDataHolder The root data holder 146 * @param includeNotValidatedComments True to include the comments that are not validated 147 * @param includeValidatedComments True to include the comments that are validated 148 * @return the list of comments 149 * @throws AmetysRepositoryException If an error occurred 150 */ 151 public static List<Comment> getComments(ModifiableModelLessDataHolder rootDataHolder, boolean includeNotValidatedComments, boolean includeValidatedComments) throws AmetysRepositoryException 152 { 153 return getComments(rootDataHolder, includeNotValidatedComments, includeValidatedComments, false); 154 } 155 156 /** 157 * Get the comments in the given root data holder 158 * @param rootDataHolder The root data holder 159 * @param includeNotValidatedComments True to include the comments that are not validated 160 * @param includeValidatedComments True to include the comments that are validated 161 * @param isRecursive true if we want to have sub comments 162 * @return the list of comments 163 * @throws AmetysRepositoryException If an error occurred 164 */ 165 //public static <T extends AbstractComment> List<T> getComments(ModifiableModelLessDataHolder rootDataHolder, boolean includeNotValidatedComments, boolean includeValidatedComments, boolean isRecursive, BiFunction<ModifiableModelLessDataHolder, String, T> commentCreator) throws AmetysRepositoryException 166 public static List<Comment> getComments(ModifiableModelLessDataHolder rootDataHolder, boolean includeNotValidatedComments, boolean includeValidatedComments, boolean isRecursive) throws AmetysRepositoryException 167 { 168 return getComments(rootDataHolder, includeNotValidatedComments, includeValidatedComments, isRecursive, getCreationFunction()); 169 } 170 171 @Override 172 protected void update() 173 { 174 long validated = 0; 175 long notValidated = 0; 176 177 ModifiableModelLessDataHolder dataHolder = _rootDataHolder; 178 if (isSubComment()) 179 { 180 dataHolder = getCommentParent()._rootDataHolder; 181 } 182 183 List<Comment> comments = getComments(dataHolder, true, true, false, getCreationFunction()); 184 185 for (AbstractComment comment : comments) 186 { 187 if (comment.isValidated()) 188 { 189 validated++; 190 } 191 else 192 { 193 notValidated++; 194 } 195 } 196 197 dataHolder.setValue(METADATA_COMMENTS_VALIDATED, validated); 198 dataHolder.setValue(METADATA_COMMENTS_NOTVALIDATED, notValidated); 199 } 200 201 @SuppressWarnings("unchecked") 202 @Override 203 public Comment getCommentParent() 204 { 205 if (isSubComment()) 206 { 207 String parentId = StringUtils.substringBeforeLast(this.getId(), ID_SEPARATOR); 208 return getComment(_rootDataHolder, parentId); 209 } 210 return null; 211 } 212 213 @SuppressWarnings("unchecked") 214 @Override 215 public List<Comment> getSubComment(boolean includeNotValidatedComments, boolean includeValidatedComments) 216 { 217 return getComments(this, includeNotValidatedComments, includeValidatedComments); 218 } 219 220 /** 221 * Create sub comment from this comment 222 * 223 * @return the sub comment 224 */ 225 @SuppressWarnings("unchecked") 226 @Override 227 public Comment createSubComment() 228 { 229 return new Comment(this); 230 } 231 232 @SuppressWarnings("unchecked") 233 @Override 234 public Comment createSubComment(String commentId, ZonedDateTime creationDate) 235 { 236 return new Comment(this, commentId, creationDate); 237 } 238 239 private static BiFunction<ModifiableModelLessDataHolder, String, Comment> getCreationFunction() 240 { 241 return (dataHolder, name) -> 242 { 243 Comment comment = new Comment(dataHolder, name); 244 return comment; 245 }; 246 } 247 248 /** 249 * Extract users mentioned in the comment 250 * @return the mentioned users 251 */ 252 public Collection<UserIdentity> extractMentions() 253 { 254 String content = getContent(); 255 256 return MentionUtils.extractMentionedUsersFromSimpleText(content); 257 } 258}