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.util.ArrayList;
020import java.util.Date;
021import java.util.List;
022
023import org.ametys.plugins.repository.AmetysRepositoryException;
024import org.ametys.plugins.repository.metadata.ModifiableCompositeMetadata;
025
026/**
027 * A comment on a commentable content
028 */
029public class Comment
030{
031    /** Constants for comments Metadat* */
032    public static final String METADATA_COMMENTS = "comments";
033    /** Constants for comments Metadata not validted */
034    public static final String METADATA_COMMENTS_VALIDATED = "validated";
035    /** Constants for comments Metadata validated */
036    public static final String METADATA_COMMENTS_NOTVALIDATED = "not-validated";
037
038    /** Constants for creation Metadata */
039    public static final String METADATA_COMMENT_CREATIONDATE = "creation";
040    /** Constants for author name Metadata */
041    public static final String METADATA_COMMENT_AUTHORNAME = "author-name";
042    /** Constants for author email Metadata */
043    public static final String METADATA_COMMENT_AUTHOREMAIL = "author-email";
044    /** Constants for author email hidden Metadata */
045    public static final String METADATA_COMMENT_AUTHOREMAIL_HIDDEN = "author-email-hidden";
046    /** Constants for author url Metadata */
047    public static final String METADATA_COMMENT_AUTHORURL = "author-url";
048    /** Constants for the content Metadata */
049    public static final String METADATA_COMMENT_CONTENT = "content";
050    /** Constants for the validated status Metadata */
051    public static final String METADATA_COMMENT_VALIDATED = "validated";
052
053    /** The content to comment */
054    protected ModifiableCompositeMetadata _contentMetadataHolder;
055    /** The metadata node of the comment */
056    protected ModifiableCompositeMetadata _metadata;
057    /** The id of the comment (unique in the content) */
058    protected String _id;
059    
060    /**
061     * Retrieves a comment by its id
062     * @param contentUnversionnedMetadataHolder The unversionned metadate holder of the content hosting the comment
063     * @param commentId The id of the comment to retrieve
064     * @throws AmetysRepositoryException if an error occured
065     */
066    public Comment(ModifiableCompositeMetadata contentUnversionnedMetadataHolder, String commentId)
067    {
068        _contentMetadataHolder = contentUnversionnedMetadataHolder;
069        _id = commentId;
070        _metadata = _contentMetadataHolder.getCompositeMetadata(METADATA_COMMENTS).getCompositeMetadata(_id);
071    }
072    
073    /**
074     * Creates a new comment on the content
075     * @param contentUnversionnedMetadataHolder The unversionned metadate holder of the content where to add the new comment 
076     */
077    public Comment(ModifiableCompositeMetadata contentUnversionnedMetadataHolder)
078    {
079        _contentMetadataHolder = contentUnversionnedMetadataHolder;
080
081        ModifiableCompositeMetadata parent = _contentMetadataHolder.getCompositeMetadata(METADATA_COMMENTS, true);
082
083        String base = "comment-";
084        int i = 0;
085        while (parent.hasMetadata(base + i))
086        {
087            i++;
088        }
089
090        _id = base + i;
091        _metadata = _contentMetadataHolder.getCompositeMetadata(METADATA_COMMENTS, true).getCompositeMetadata(_id, true);
092        _metadata.setMetadata(METADATA_COMMENT_CREATIONDATE, new Date());
093        
094        update();
095    }
096    
097    /**
098     * Get the composite metadata object holding the comment
099     * @return the comment
100     */
101    public ModifiableCompositeMetadata getMetadata()
102    {
103        return _metadata;
104    }
105    
106    /**
107     * The comment id (unique to the content)
108     * @return The id. Cannot be null.
109     */
110    public String getId()
111    {
112        return _id;
113    }
114    /**
115     * Get the date and time the comment was created
116     * @return The non null date of creation of the comment.
117     */
118    public Date getCreationDate()
119    {
120        return _metadata.getDate(METADATA_COMMENT_CREATIONDATE);
121    }
122    
123    /**
124     * Get the readable name of the author.
125     * @return The full name. Can be null.
126     */
127    public String getAuthorName()
128    {
129        if (_metadata.hasMetadata(METADATA_COMMENT_AUTHORNAME))
130        {
131            return _metadata.getString(METADATA_COMMENT_AUTHORNAME);
132        }
133        else
134        {
135            return null;
136        }
137    }
138    /**
139     * Set the readable name of the author.
140     * @param name The full name. Can be null to remove the name.
141     */
142    public void setAuthorName(String name)
143    {
144        if (name != null)
145        {
146            _metadata.setMetadata(METADATA_COMMENT_AUTHORNAME, name);
147        }
148        else if (_metadata.hasMetadata(METADATA_COMMENT_AUTHORNAME))
149        {
150            _metadata.removeMetadata(METADATA_COMMENT_AUTHORNAME);
151        }
152    }
153    
154    /**
155     * Get the email of the author.
156     * @return The ameil. Can be null.
157     */
158    public String getAuthorEmail()
159    {
160        if (_metadata.hasMetadata(METADATA_COMMENT_AUTHOREMAIL))
161        {
162            return _metadata.getString(METADATA_COMMENT_AUTHOREMAIL);
163        }
164        else
165        {
166            return null;
167        }
168    }
169    /**
170     * Set the email of the author.
171     * @param email The email. Can be null to remove the email.
172     */
173    public void setAuthorEmail(String email)
174    {
175        if (email != null)
176        {
177            _metadata.setMetadata(METADATA_COMMENT_AUTHOREMAIL, email);
178        }
179        else if (_metadata.hasMetadata(METADATA_COMMENT_AUTHOREMAIL))
180        {
181            _metadata.removeMetadata(METADATA_COMMENT_AUTHOREMAIL);
182        }
183    }
184    
185    /**
186     * Get the url given by the author as its personnal site url.
187     * @return The url. Can be null.
188     */
189    public String getAuthorURL()
190    {
191        if (_metadata.hasMetadata(METADATA_COMMENT_AUTHORURL))
192        {
193            return _metadata.getString(METADATA_COMMENT_AUTHORURL);
194        }
195        else
196        {
197            return null;
198        }
199    }
200    /**
201     * Set the personnal site url of the author
202     * @param url The url. Can be null to remove url.
203     */
204    public void setAuthorURL(String url)
205    {
206        if (url != null)
207        {
208            _metadata.setMetadata(METADATA_COMMENT_AUTHORURL, url);
209        }
210        else if (_metadata.hasMetadata(METADATA_COMMENT_AUTHORURL))
211        {
212            _metadata.removeMetadata(METADATA_COMMENT_AUTHORURL);
213        }
214    }
215    
216    /**
217     * Does the email of the authors have to be hidden ?
218     * @return true (default value) if the email does not have to appears to others users. Can still be used for administration.
219     */
220    public boolean isEmailHidden()
221    {
222        if (_metadata.hasMetadata(METADATA_COMMENT_AUTHOREMAIL_HIDDEN))
223        {
224            return _metadata.getBoolean(METADATA_COMMENT_AUTHOREMAIL_HIDDEN);
225        }
226        else
227        {
228            return true;
229        }
230    }
231    /**
232     * Set the email hidden status.
233     * @param hideEmail true to set the email as hidden.
234     */
235    public void setEmailHiddenStatus(boolean hideEmail)
236    {
237        _metadata.setMetadata(METADATA_COMMENT_AUTHOREMAIL_HIDDEN, hideEmail);
238    }
239    
240    /**
241     * Get the content of the comment. A simple String (with \n or \t).
242     * @return The content. Can be null.
243     */
244    public String getContent()
245    {
246        if (_metadata.hasMetadata(METADATA_COMMENT_CONTENT))
247        {
248            return _metadata.getString(METADATA_COMMENT_CONTENT);
249        }
250        else
251        {
252            return null;
253        }
254    }
255    /**
256     * Set the content of the comment.
257     * @param content The content to set. Can be null to remove the content. Have to be a simple String (with \n or \t).
258     */
259    public void setContent(String content)
260    {
261        if (content != null)
262        {
263            _metadata.setMetadata(METADATA_COMMENT_CONTENT, content);
264        }
265        else if (_metadata.hasMetadata(METADATA_COMMENT_CONTENT))
266        {
267            _metadata.removeMetadata(METADATA_COMMENT_CONTENT);
268        }
269    }
270    
271    /**
272     * Is the comment validated
273     * @return the status of validation of the comment
274     */
275    public boolean isValidated()
276    {
277        if (_metadata.hasMetadata(METADATA_COMMENT_VALIDATED))
278        {
279            return _metadata.getBoolean(METADATA_COMMENT_VALIDATED);
280        }
281        else
282        {
283            return false;
284        }
285    }
286    
287    /**
288     * Set the validation status of the comment
289     * @param validated true the comment is validated
290     */
291    public void setValidated(boolean validated)
292    {
293        _metadata.setMetadata(METADATA_COMMENT_VALIDATED, validated);
294        update();
295    }
296    
297    /**
298     * Remove the comment.
299     */
300    public void remove()
301    {
302        _contentMetadataHolder.getCompositeMetadata(METADATA_COMMENTS).removeMetadata(_id);
303        update();
304    }
305    
306    /**
307     * Update the comment tag statistics
308     */
309    protected void update()
310    {
311        long validated = 0;
312        long notValidated = 0;
313        
314        List<Comment> comments = getComments(_contentMetadataHolder, true, true);
315        
316        for (Comment comment : comments)
317        {
318            if (comment.isValidated())
319            {
320                validated++;
321            }
322            else
323            {
324                notValidated++;
325            }
326        }
327        
328        _contentMetadataHolder.getCompositeMetadata(METADATA_COMMENTS).setMetadata(METADATA_COMMENTS_VALIDATED, validated);
329        _contentMetadataHolder.getCompositeMetadata(METADATA_COMMENTS).setMetadata(METADATA_COMMENTS_NOTVALIDATED, notValidated);
330    }
331
332    /**
333     * Get a comment
334     * @param contentUnversionnedMetadataHolder the content
335     * @param commentId The comment
336     * @return The comment
337     * @throws AmetysRepositoryException if the comment does not exist
338     */
339    public static Comment getComment(ModifiableCompositeMetadata contentUnversionnedMetadataHolder, String commentId) throws AmetysRepositoryException
340    {
341        return new Comment(contentUnversionnedMetadataHolder, commentId);
342    }
343    
344    /**
345     * Get the comments of a content 
346     * @param contentUnversionnedMetadataHolder The content to update
347     * @param includeNotValidatedComments True to include the comments that are not validated
348     * @param includeValidatedComments True to include the comments that are validated
349     * @return the list of comments
350     * @throws AmetysRepositoryException If an error occurred
351     */
352    public static List<Comment> getComments(ModifiableCompositeMetadata contentUnversionnedMetadataHolder, boolean includeNotValidatedComments, boolean includeValidatedComments) throws AmetysRepositoryException
353    {
354        List<Comment> comments = new ArrayList<>();
355        
356        if (contentUnversionnedMetadataHolder.hasMetadata(METADATA_COMMENTS))
357        {
358            String[] ids = contentUnversionnedMetadataHolder.getCompositeMetadata(METADATA_COMMENTS).getMetadataNames();
359            for (String id : ids)
360            {
361                if (METADATA_COMMENTS_NOTVALIDATED.equals(id) || METADATA_COMMENTS_VALIDATED.equals(id))
362                {
363                    continue;
364                }
365                
366                Comment c = new Comment(contentUnversionnedMetadataHolder, id);
367                if (includeNotValidatedComments && !c.isValidated() || includeValidatedComments && c.isValidated())
368                {
369                    comments.add(c);
370                }
371            }
372        }
373        
374        return comments;
375    }
376}