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.List;
021import java.util.Optional;
022import java.util.function.BiFunction;
023
024import org.apache.commons.lang3.StringUtils;
025
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}
032 */
033public class Comment extends AbstractComment
034{
035    
036    /**
037     * Retrieves a comment by its id
038     * @param rootDataHolder The root data holder hosting the first level of comments
039     * @param commentId The id of the comment to retrieve
040     * @throws AmetysRepositoryException if an error occurred
041     */
042    public Comment(ModifiableModelLessDataHolder rootDataHolder, String commentId)
043    {
044        super(rootDataHolder, commentId);
045    }
046    
047    /**
048     * Creates a new comment
049     * @param dataHolder The data holder where to add the new comment 
050     */
051    public Comment(ModifiableModelLessDataHolder dataHolder)
052    {
053        super(dataHolder, Optional.empty(), Optional.empty());
054    }
055    
056    /**
057     * Creates a new comment, with the given id and creation date
058     * This method allows to create a comment from existing data (ex: data import from archive) 
059     * The id is not generated here, the source is trusted. Be careful using this method
060     * @param dataHolder The data holder where to add the new comment
061     * @param commentId the comment's id
062     * @param creationDate the comment's creation date
063     */
064    public Comment(ModifiableModelLessDataHolder dataHolder, String commentId, ZonedDateTime creationDate)
065    {
066        super(dataHolder, Optional.ofNullable(commentId), Optional.ofNullable(creationDate));
067    }
068    
069    private Comment(ModifiableModelLessDataHolder dataHolder, Optional<String> commentId, Optional<ZonedDateTime> creationDate)
070    {
071        super(dataHolder, commentId, creationDate);
072    }
073    
074    /**
075     * Creates a new sub comment of the comment
076     * @param comment The parent comment
077     */
078    public Comment(Comment comment)
079    {
080        this(comment, Optional.empty(), Optional.empty());
081    }
082    
083    /**
084     * Creates a new sub comment of the comment, with the given id and creation date
085     * This method allow to create a sub comment from existing data (ex: data import from archive) 
086     * The id is not generated here, the source is trusted. Be careful using this method
087     * @param comment The parent comment
088     * @param commentId the sub comment's id
089     * @param creationDate the sub comment's creation date
090     */
091    public Comment(Comment comment, String commentId, ZonedDateTime creationDate)
092    {
093        this(comment, Optional.ofNullable(commentId), Optional.ofNullable(creationDate));
094    }
095    
096    private Comment(Comment comment, Optional<String> commentId, Optional<ZonedDateTime> creationDate)
097    {
098        super(comment, commentId, creationDate);
099    }
100
101    /**
102     * Get a comment
103     * @param rootDataHolder The root data holder of the first level of comments
104     * @param commentId The comment identifier
105     * @return The comment
106     * @throws AmetysRepositoryException if the comment does not exist
107     */
108    public static Comment getComment(ModifiableModelLessDataHolder rootDataHolder, String commentId) throws AmetysRepositoryException
109    {
110        return new Comment(rootDataHolder, commentId);
111    }
112    
113    /**
114     * Get the sub comments of the given comment
115     * @param parentComment The parent comment
116     * @param includeNotValidatedComments True to include the comments that are not validated
117     * @param includeValidatedComments True to include the comments that are validated
118     * @return the list of sub comments
119     * @throws AmetysRepositoryException If an error occurred
120     */
121    public static List<Comment> getComments(Comment parentComment, boolean includeNotValidatedComments, boolean includeValidatedComments) throws AmetysRepositoryException
122    {
123        return getComments(parentComment, includeNotValidatedComments, includeValidatedComments, false);
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     * @param withSubComment true if we want to get all child comments
132     * @return the list of comments
133     * @throws AmetysRepositoryException If an error occurred
134     */
135    public static List<Comment> getComments(Comment parentComment, boolean includeNotValidatedComments, boolean includeValidatedComments, boolean withSubComment) throws AmetysRepositoryException
136    {
137        return getComments(parentComment, includeNotValidatedComments, includeValidatedComments, withSubComment, getCreationFunction());
138    }
139
140    /**
141     * Get the comments in the given root data holder
142     * @param rootDataHolder The root data holder
143     * @param includeNotValidatedComments True to include the comments that are not validated
144     * @param includeValidatedComments True to include the comments that are validated
145     * @return the list of comments
146     * @throws AmetysRepositoryException If an error occurred
147     */
148    public static List<Comment> getComments(ModifiableModelLessDataHolder rootDataHolder, boolean includeNotValidatedComments, boolean includeValidatedComments) throws AmetysRepositoryException
149    {
150        return getComments(rootDataHolder, includeNotValidatedComments, includeValidatedComments, false);
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     * @param isRecursive true if we want to have sub comments
159     * @return the list of comments
160     * @throws AmetysRepositoryException If an error occurred
161     */
162    //public static <T extends AbstractComment> List<T> getComments(ModifiableModelLessDataHolder rootDataHolder, boolean includeNotValidatedComments, boolean includeValidatedComments, boolean isRecursive, BiFunction<ModifiableModelLessDataHolder, String, T> commentCreator) throws AmetysRepositoryException
163    public static List<Comment> getComments(ModifiableModelLessDataHolder                         rootDataHolder, boolean includeNotValidatedComments, boolean includeValidatedComments, boolean isRecursive) throws AmetysRepositoryException
164    {
165        return getComments(rootDataHolder, includeNotValidatedComments, includeValidatedComments, isRecursive, getCreationFunction());
166    }
167    
168    @Override
169    protected void update()
170    {
171        long validated = 0;
172        long notValidated = 0;
173
174        ModifiableModelLessDataHolder dataHolder = _rootDataHolder;
175        if (isSubComment())
176        {
177            dataHolder = getCommentParent()._rootDataHolder;
178        }
179        
180        List<Comment> comments = getComments(dataHolder, true, true, false, getCreationFunction());
181
182        for (AbstractComment comment : comments)
183        {
184            if (comment.isValidated())
185            {
186                validated++;
187            }
188            else
189            {
190                notValidated++;
191            }
192        }
193
194        dataHolder.setValue(METADATA_COMMENTS_VALIDATED, validated);
195        dataHolder.setValue(METADATA_COMMENTS_NOTVALIDATED, notValidated);
196    }
197    
198    @SuppressWarnings("unchecked")
199    @Override
200    public Comment getCommentParent()
201    {
202        if (isSubComment())
203        {
204            String parentId = StringUtils.substringBeforeLast(this.getId(), ID_SEPARATOR);
205            return getComment(_rootDataHolder, parentId);
206        }
207        return null;
208    }
209
210    @SuppressWarnings("unchecked")
211    @Override
212    public List<Comment> getSubComment(boolean includeNotValidatedComments, boolean includeValidatedComments)
213    {
214        return getComments(this, includeNotValidatedComments, includeValidatedComments);
215    }
216
217    /**
218     * Create sub comment from this comment
219     * 
220     * @return the sub comment
221     */
222    @SuppressWarnings("unchecked")
223    @Override
224    public Comment createSubComment()
225    {
226        return new Comment(this);
227    }
228
229    @SuppressWarnings("unchecked")
230    @Override
231    public Comment createSubComment(String commentId, ZonedDateTime creationDate)
232    {
233        return new Comment(this, commentId, creationDate);
234    }
235    
236    private static BiFunction<ModifiableModelLessDataHolder, String, Comment> getCreationFunction()
237    {
238        return (dataHolder, name) ->
239        {
240            Comment comment = new Comment(dataHolder, name);
241            return comment;
242        };
243    }
244}