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.ArrayList; 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.ReactionableObject; 029import org.ametys.cms.repository.ReactionableObjectHelper; 030import org.ametys.cms.repository.ReportableObject; 031import org.ametys.cms.repository.ReportableObjectHelper; 032import org.ametys.core.user.UserIdentity; 033import org.ametys.plugins.repository.AmetysRepositoryException; 034import org.ametys.plugins.repository.data.holder.ModelLessDataHolder; 035import org.ametys.plugins.repository.data.holder.ModifiableModelLessDataHolder; 036import org.ametys.plugins.repository.data.holder.group.ModifiableModelLessComposite; 037import org.ametys.plugins.repository.data.repositorydata.ModifiableRepositoryData; 038import org.ametys.runtime.model.ModelItem; 039import org.ametys.runtime.model.type.ModelItemTypeConstants; 040/** 041 * A comment on a {@link CommentableAmetysObject} 042 */ 043public abstract class AbstractComment implements ReactionableObject, ReportableObject 044{ 045 /** Constants for comments Metadata not validted */ 046 public static final String METADATA_COMMENTS_VALIDATED = "validated"; 047 /** Constants for comments Metadata validated */ 048 public static final String METADATA_COMMENTS_NOTVALIDATED = "not-validated"; 049 /** Constants for sub comments data name */ 050 public static final String SUB_COMMENTS_DATA_NAME = "comments"; 051 /** Constants for creation Metadata */ 052 public static final String METADATA_COMMENT_CREATIONDATE = "creation"; 053 /** Constants for last modification Metadata */ 054 public static final String METADATA_COMMENT_LAST_MODIFICATION_DATE = "last-modification"; 055 /** Constants for author Metadata */ 056 public static final String METADATA_COMMENT_AUTHOR = "author"; 057 /** Constants for author name Metadata */ 058 public static final String METADATA_COMMENT_AUTHORNAME = "author-name"; 059 /** Constants for author email Metadata */ 060 public static final String METADATA_COMMENT_AUTHOREMAIL = "author-email"; 061 /** Constants for author email hidden Metadata */ 062 public static final String METADATA_COMMENT_AUTHOREMAIL_HIDDEN = "author-email-hidden"; 063 /** Constants for author url Metadata */ 064 public static final String METADATA_COMMENT_AUTHORURL = "author-url"; 065 /** Constants for the content Metadata */ 066 public static final String METADATA_COMMENT_CONTENT = "content"; 067 /** Constants for the validated status Metadata */ 068 public static final String METADATA_COMMENT_VALIDATED = "validated"; 069 /** Constants for the is edited status Metadata */ 070 public static final String METADATA_COMMENT_IS_EDITED = "is-edited"; 071 /** Constants for the is deleted status Metadata */ 072 public static final String METADATA_COMMENT_IS_DELETED = "is-deleted"; 073 /** Constants for the is marked status Metadata */ 074 public static final String METADATA_COMMENT_IS_ACCEPTED = "is-accepted"; 075 /** Constant for the prefix of comments' name */ 076 public static final String COMMENT_NAME_PREFIX = "comment-"; 077 078 /** Constants for the separator */ 079 public static final String ID_SEPARATOR = "_"; 080 081 /** The root data holder where to store the first level of comments */ 082 protected ModifiableModelLessDataHolder _rootDataHolder; 083 /** The node of the comment */ 084 protected ModifiableModelLessComposite _commentComposite; 085 /** The id of the comment (unique in the ametys object) */ 086 protected String _id; 087 088 /** 089 * Retrieves a comment by its id 090 * @param rootDataHolder The root data holder hosting the first level of comments 091 * @param commentId The id of the comment to retrieve 092 * @throws AmetysRepositoryException if an error occurred 093 */ 094 public AbstractComment(ModifiableModelLessDataHolder rootDataHolder, String commentId) 095 { 096 _rootDataHolder = rootDataHolder; 097 _id = commentId; 098 099 String commentDataPath = getCommentDataPath(_id); 100 _commentComposite = _rootDataHolder.getComposite(commentDataPath); 101 } 102 103 /** 104 * Creates a new comment 105 * @param dataHolder The data holder where to add the new comment 106 */ 107 public AbstractComment(ModifiableModelLessDataHolder dataHolder) 108 { 109 this(dataHolder, Optional.empty(), Optional.empty()); 110 } 111 112 /** 113 * Creates a new comment, with the given id and creation date 114 * This method allows to create a comment from existing data (ex: data import from archive) 115 * The id is not generated here, the source is trusted. Be careful using this method 116 * @param dataHolder The data holder where to add the new comment 117 * @param commentId the comment's id 118 * @param creationDate the comment's creation date 119 */ 120 public AbstractComment(ModifiableModelLessDataHolder dataHolder, String commentId, ZonedDateTime creationDate) 121 { 122 this(dataHolder, Optional.ofNullable(commentId), Optional.ofNullable(creationDate)); 123 } 124 125 /** 126 * Creates a new comment on the content, with the given id and creation date 127 * This method allow to create a comment from existing data (ex: data import from archive) 128 * The id is not generated here, the source is trusted. Be careful using this method 129 * @param dataHolder The data holder of the content where to add the new comment 130 * @param commentId the comment's id 131 * @param creationDate the comment's creation date 132 */ 133 protected AbstractComment(ModifiableModelLessDataHolder dataHolder, Optional<String> commentId, Optional<ZonedDateTime> creationDate) 134 { 135 _rootDataHolder = dataHolder; 136 137 _id = commentId.orElseGet(() -> _getNextCommentName(_rootDataHolder)); 138 _commentComposite = _rootDataHolder.getComposite(_id, true); 139 _commentComposite.setValue(METADATA_COMMENT_CREATIONDATE, creationDate.orElseGet(ZonedDateTime::now)); 140 141 update(); 142 } 143 144 /** 145 * Creates a new sub comment of the comment 146 * @param comment The parent comment 147 */ 148 public AbstractComment(AbstractComment comment) 149 { 150 this(comment, Optional.empty(), Optional.empty()); 151 } 152 153 /** 154 * Creates a new sub comment of the comment, with the given id and creation date 155 * This method allow to create a sub comment from existing data (ex: data import from archive) 156 * The id is not generated here, the source is trusted. Be careful using this method 157 * @param comment The parent comment 158 * @param commentId the sub comment's id 159 * @param creationDate the sub comment's creation date 160 */ 161 public AbstractComment(AbstractComment comment, String commentId, ZonedDateTime creationDate) 162 { 163 this(comment, Optional.ofNullable(commentId), Optional.ofNullable(creationDate)); 164 } 165 166 /** 167 * Creates a new sub comment of the comment, with the given id and creation date 168 * This method allow to create a sub comment from existing data (ex: data import from archive) 169 * The id is not generated here, the source is trusted. Be careful using this method 170 * @param comment The parent comment 171 * @param commentId the sub comment's id 172 * @param creationDate the sub comment's creation date 173 */ 174 protected AbstractComment(AbstractComment comment, Optional<String> commentId, Optional<ZonedDateTime> creationDate) 175 { 176 _rootDataHolder = comment._rootDataHolder; 177 ModifiableModelLessComposite subCommentsDataHolder = comment._commentComposite.getComposite(SUB_COMMENTS_DATA_NAME, true); 178 179 String commentName = commentId.map(id -> StringUtils.substringAfterLast(id, ID_SEPARATOR)) 180 .orElseGet(() -> _getNextCommentName(subCommentsDataHolder)); 181 _id = commentId.orElseGet(() -> comment.getId() + ID_SEPARATOR + commentName); 182 183 _commentComposite = subCommentsDataHolder.getComposite(commentName, true); 184 _commentComposite.setValue(METADATA_COMMENT_CREATIONDATE, creationDate.orElseGet(ZonedDateTime::now)); 185 186 update(); 187 } 188 189 private static String _getNextCommentName(ModelLessDataHolder dataHolder) 190 { 191 String base = COMMENT_NAME_PREFIX; 192 int i = 0; 193 while (dataHolder.hasValueOrEmpty(base + i)) 194 { 195 i++; 196 } 197 198 return base + i; 199 } 200 201 /** 202 * Retrieves the path of the comment with the given identifier 203 * @param commentId the comment identifier 204 * @return the path of the comment 205 */ 206 protected String getCommentDataPath(String commentId) 207 { 208 String[] commentIdSegments = commentId.split(ID_SEPARATOR); 209 return StringUtils.join(commentIdSegments, ModelItem.ITEM_PATH_SEPARATOR + SUB_COMMENTS_DATA_NAME + ModelItem.ITEM_PATH_SEPARATOR); 210 } 211 212 /** 213 * Retrieves the repository data of the {@link AbstractComment} 214 * @return the repository data of the {@link AbstractComment} 215 */ 216 public ModifiableRepositoryData getRepositoryData() 217 { 218 return _commentComposite.getRepositoryData(); 219 } 220 221 /** 222 * The comment id (unique to the ametys object) 223 * @return The id. Cannot be null. 224 */ 225 public String getId() 226 { 227 return _id; 228 } 229 230 /** 231 * Get the date and time the comment was created 232 * @return The non null date of creation of the comment. 233 */ 234 public ZonedDateTime getCreationDate() 235 { 236 return _commentComposite.getValue(METADATA_COMMENT_CREATIONDATE); 237 } 238 239 /** 240 * Get the date and time the comment was last modified 241 * @return The non null date of last modification of the comment. 242 */ 243 public ZonedDateTime getLastModificationDate() 244 { 245 return _commentComposite.getValue(METADATA_COMMENT_LAST_MODIFICATION_DATE); 246 } 247 248 /** 249 * Set the date and time the comment was last modified 250 * @param lastModificationDate the last modification date 251 */ 252 public void setLastModificationDate(ZonedDateTime lastModificationDate) 253 { 254 _commentComposite.setValue(METADATA_COMMENT_LAST_MODIFICATION_DATE, lastModificationDate); 255 } 256 257 /** 258 * Get the comment's author 259 * @return the comment's author 260 */ 261 public UserIdentity getAuthor() 262 { 263 return _commentComposite.getValueOfType(METADATA_COMMENT_AUTHOR, org.ametys.cms.data.type.ModelItemTypeConstants.USER_ELEMENT_TYPE_ID); 264 } 265 266 /** 267 * Set the comment's author. 268 * @param author the author. Can be null to remove the name. 269 */ 270 public void setAuthor(UserIdentity author) 271 { 272 _commentComposite.setValue(METADATA_COMMENT_AUTHOR, author, org.ametys.cms.data.type.ModelItemTypeConstants.USER_ELEMENT_TYPE_ID); 273 } 274 275 /** 276 * Get the readable name of the author. 277 * @return The full name. Can be null. 278 */ 279 public String getAuthorName() 280 { 281 return _commentComposite.getValueOfType(METADATA_COMMENT_AUTHORNAME, ModelItemTypeConstants.STRING_TYPE_ID); 282 } 283 284 /** 285 * Set the readable name of the author. 286 * @param name The full name. Can be null to remove the name. 287 */ 288 public void setAuthorName(String name) 289 { 290 _commentComposite.setValue(METADATA_COMMENT_AUTHORNAME, name, ModelItemTypeConstants.STRING_TYPE_ID); 291 } 292 293 /** 294 * Get the email of the author. 295 * @return The ameil. Can be null. 296 */ 297 public String getAuthorEmail() 298 { 299 return _commentComposite.getValueOfType(METADATA_COMMENT_AUTHOREMAIL, ModelItemTypeConstants.STRING_TYPE_ID); 300 } 301 302 /** 303 * Set the email of the author. 304 * @param email The email. Can be null to remove the email. 305 */ 306 public void setAuthorEmail(String email) 307 { 308 _commentComposite.setValue(METADATA_COMMENT_AUTHOREMAIL, email, ModelItemTypeConstants.STRING_TYPE_ID); 309 } 310 311 /** 312 * Get the url given by the author as its personal site url. 313 * @return The url. Can be null. 314 */ 315 public String getAuthorURL() 316 { 317 return _commentComposite.getValueOfType(METADATA_COMMENT_AUTHORURL, ModelItemTypeConstants.STRING_TYPE_ID); 318 } 319 320 /** 321 * Set the personal site url of the author 322 * @param url The url. Can be null to remove url. 323 */ 324 public void setAuthorURL(String url) 325 { 326 _commentComposite.setValue(METADATA_COMMENT_AUTHORURL, url, ModelItemTypeConstants.STRING_TYPE_ID); 327 } 328 329 /** 330 * Does the email of the authors have to be hidden ? 331 * @return true (default value) if the email does not have to appears to others users. Can still be used for administration. 332 */ 333 public boolean isEmailHidden() 334 { 335 return _commentComposite.getValueOfType(METADATA_COMMENT_AUTHOREMAIL_HIDDEN, ModelItemTypeConstants.BOOLEAN_TYPE_ID, true); 336 } 337 /** 338 * Set the email hidden status. 339 * @param hideEmail true to set the email as hidden. 340 */ 341 public void setEmailHiddenStatus(boolean hideEmail) 342 { 343 _commentComposite.setValue(METADATA_COMMENT_AUTHOREMAIL_HIDDEN, hideEmail, ModelItemTypeConstants.BOOLEAN_TYPE_ID); 344 } 345 346 /** 347 * Does the comment is edited 348 * @return true the email is edited 349 */ 350 public boolean isEdited() 351 { 352 return _commentComposite.getValueOfType(METADATA_COMMENT_IS_EDITED, ModelItemTypeConstants.BOOLEAN_TYPE_ID, false); 353 } 354 /** 355 * Set the comment to edited. 356 * @param isEdited true to set the comment to edited. 357 */ 358 public void setEdited(boolean isEdited) 359 { 360 _commentComposite.setValue(METADATA_COMMENT_IS_EDITED, isEdited, ModelItemTypeConstants.BOOLEAN_TYPE_ID); 361 } 362 363 /** 364 * Does the comment is deleted 365 * @return true the comment is deleted 366 */ 367 public boolean isDeleted() 368 { 369 return _commentComposite.getValueOfType(METADATA_COMMENT_IS_DELETED, ModelItemTypeConstants.BOOLEAN_TYPE_ID, false); 370 } 371 /** 372 * Set the comment to deleted. 373 * @param isEdited true to set the comment to deleted. 374 */ 375 public void setDeleted(boolean isEdited) 376 { 377 _commentComposite.setValue(METADATA_COMMENT_IS_DELETED, isEdited, ModelItemTypeConstants.BOOLEAN_TYPE_ID); 378 } 379 380 /** 381 * Get the content of the comment. A simple String (with \n or \t). 382 * @return The content. Can be null. 383 */ 384 public String getContent() 385 { 386 return _commentComposite.getValueOfType(METADATA_COMMENT_CONTENT, ModelItemTypeConstants.STRING_TYPE_ID); 387 } 388 /** 389 * Set the content of the comment. 390 * @param content The content to set. Can be null to remove the content. Have to be a simple String (with \n or \t). 391 */ 392 public void setContent(String content) 393 { 394 _commentComposite.setValue(METADATA_COMMENT_CONTENT, content, ModelItemTypeConstants.STRING_TYPE_ID); 395 } 396 397 398 /** 399 * Is the comment validated 400 * @return the status of validation of the comment 401 */ 402 public boolean isValidated() 403 { 404 return _commentComposite.getValueOfType(METADATA_COMMENT_VALIDATED, ModelItemTypeConstants.BOOLEAN_TYPE_ID, false); 405 } 406 407 /** 408 * Set the validation status of the comment 409 * @param validated true the comment is validated 410 */ 411 public void setValidated(boolean validated) 412 { 413 _commentComposite.setValue(METADATA_COMMENT_VALIDATED, validated, ModelItemTypeConstants.BOOLEAN_TYPE_ID); 414 update(); 415 } 416 417 public void addReport() 418 { 419 ReportableObjectHelper.addReport(_commentComposite); 420 } 421 422 public void setReportsCount(long reportsCount) 423 { 424 ReportableObjectHelper.setReportsCount(_commentComposite, reportsCount); 425 } 426 427 public void clearReports() 428 { 429 ReportableObjectHelper.clearReports(_commentComposite); 430 } 431 432 public long getReportsCount() 433 { 434 return ReportableObjectHelper.getReportsCount(_commentComposite); 435 } 436 437 /** 438 * Remove the comment. 439 */ 440 public void remove() 441 { 442 String commentDataPath = getCommentDataPath(_id); 443 _rootDataHolder.removeValue(commentDataPath); 444 update(); 445 } 446 447 /** 448 * Get sub comments of the comment 449 * @param <T> type of the value to retrieve 450 * @param includeNotValidatedComments True to include the comments that are not validated 451 * @param includeValidatedComments True to include the comments that are validated 452 * @return the list of comments 453 */ 454 public abstract <T extends AbstractComment> List<T> getSubComment(boolean includeNotValidatedComments, boolean includeValidatedComments); 455 456 /** 457 * Create sub comment from this comment 458 * @param <T> type of the value to retrieve 459 * @return the sub comment 460 */ 461 public abstract <T extends AbstractComment> T createSubComment(); 462 463 /** 464 * Creates a sub comment from this comment, with the given id and creation date 465 * This method allow to create a sub comment from existing data (ex: data import from archive) 466 * The id is not generated here, the source is trusted. Be careful using this method 467 * @param <T> type of the value to retrieve 468 * @param commentId the comment's id 469 * @param creationDate the comment's creation date 470 * @return the new comment 471 */ 472 public abstract <T extends AbstractComment> T createSubComment(String commentId, ZonedDateTime creationDate); 473 474 /** 475 * Update the comment tag statistics 476 */ 477 protected abstract void update(); 478 479 /** 480 * Get the sub comments of the given comment 481 * @param <T> type of the value to retrieve 482 * @param parentComment The parent comment 483 * @param includeNotValidatedComments True to include the comments that are not validated 484 * @param includeValidatedComments True to include the comments that are validated 485 * @param commentCreator function to create new comment 486 * @return the list of sub comments 487 * @throws AmetysRepositoryException If an error occurred 488 */ 489 public static <T extends AbstractComment> List<T> getComments(T parentComment, boolean includeNotValidatedComments, boolean includeValidatedComments, BiFunction<ModifiableModelLessDataHolder, String, T> commentCreator) throws AmetysRepositoryException 490 { 491 return getComments(parentComment, includeNotValidatedComments, includeValidatedComments, false, commentCreator); 492 } 493 494 /** 495 * Get the sub comments of the given comment 496 * @param <T> type of the value to retrieve 497 * @param parentComment The parent comment 498 * @param includeNotValidatedComments True to include the comments that are not validated 499 * @param includeValidatedComments True to include the comments that are validated 500 * @param withSubComment true if we want to get all child comments 501 * @param commentCreator function to create new comment 502 * @return the list of comments 503 * @throws AmetysRepositoryException If an error occurred 504 */ 505 public static <T extends AbstractComment> List<T> getComments(AbstractComment parentComment, boolean includeNotValidatedComments, boolean includeValidatedComments, boolean withSubComment, BiFunction<ModifiableModelLessDataHolder, String, T> commentCreator) throws AmetysRepositoryException 506 { 507 ModifiableModelLessComposite parentComposite = parentComment._commentComposite; 508 List<T> comments = new ArrayList<>(); 509 510 if (parentComposite.hasValue(SUB_COMMENTS_DATA_NAME, org.ametys.plugins.repository.data.type.ModelItemTypeConstants.COMPOSITE_TYPE_ID)) 511 { 512 ModifiableModelLessComposite subCommentsComposite = parentComposite.getComposite(SUB_COMMENTS_DATA_NAME); 513 return _getComments(parentComment._rootDataHolder, subCommentsComposite, parentComment.getId() + ID_SEPARATOR, includeNotValidatedComments, includeValidatedComments, withSubComment, commentCreator); 514 } 515 516 return comments; 517 } 518 519 /** 520 * Get the comments in the given root data holder 521 * @param <T> type of the value to retrieve 522 * @param rootDataHolder The root data holder 523 * @param includeNotValidatedComments True to include the comments that are not validated 524 * @param includeValidatedComments True to include the comments that are validated 525 * @param commentCreator function to create new comment 526 * @return the list of comments 527 * @throws AmetysRepositoryException If an error occurred 528 */ 529 public static <T extends AbstractComment> List<T> getComments(ModifiableModelLessDataHolder rootDataHolder, boolean includeNotValidatedComments, boolean includeValidatedComments, BiFunction<ModifiableModelLessDataHolder, String, T> commentCreator) throws AmetysRepositoryException 530 { 531 return getComments(rootDataHolder, includeNotValidatedComments, includeValidatedComments, false, commentCreator); 532 } 533 534 /** 535 * Get the comments in the given root data holder 536 * @param <T> type of the value to retrieve 537 * @param rootDataHolder The root data holder 538 * @param includeNotValidatedComments True to include the comments that are not validated 539 * @param includeValidatedComments True to include the comments that are validated 540 * @param isRecursive true if we want to have sub comments 541 * @param commentCreator function to create new comment 542 * @return the list of comments 543 * @throws AmetysRepositoryException If an error occurred 544 */ 545 public static <T extends AbstractComment> List<T> getComments(ModifiableModelLessDataHolder rootDataHolder, boolean includeNotValidatedComments, boolean includeValidatedComments, boolean isRecursive, BiFunction<ModifiableModelLessDataHolder, String, T> commentCreator) throws AmetysRepositoryException 546 { 547 return _getComments(rootDataHolder, rootDataHolder, StringUtils.EMPTY, includeNotValidatedComments, includeValidatedComments, isRecursive, commentCreator); 548 } 549 550 private static <T extends AbstractComment> List<T> _getComments(ModifiableModelLessDataHolder rootDataHolder, ModifiableModelLessDataHolder dataHolder, String commentIdPrefix, boolean includeNotValidatedComments, boolean includeValidatedComments, boolean isRecursive, BiFunction<ModifiableModelLessDataHolder, String, T> commentCreator) 551 { 552 List<T> comments = new ArrayList<>(); 553 554 for (String name : dataHolder.getDataNames()) 555 { 556 if (METADATA_COMMENTS_NOTVALIDATED.equals(name) || METADATA_COMMENTS_VALIDATED.equals(name)) 557 { 558 continue; 559 } 560 561 String id = commentIdPrefix + name; 562 T c = commentCreator.apply(rootDataHolder, id); 563 if (includeNotValidatedComments && !c.isValidated() || includeValidatedComments && c.isValidated()) 564 { 565 comments.add(c); 566 if (isRecursive) 567 { 568 comments.addAll(getComments(c, includeNotValidatedComments, includeValidatedComments, isRecursive, commentCreator)); 569 } 570 } 571 } 572 573 return comments; 574 } 575 576 @Override 577 public void addReaction(UserIdentity user, ReactionType reactionType) 578 { 579 ReactionableObjectHelper.addReaction(_commentComposite, user, reactionType); 580 } 581 582 @Override 583 public void removeReaction(UserIdentity user, ReactionType reactionType) 584 { 585 ReactionableObjectHelper.removeReaction(_commentComposite, user, reactionType); 586 } 587 588 @Override 589 public List<UserIdentity> getReactionUsers(ReactionType reactionType) 590 { 591 return ReactionableObjectHelper.getReactionUsers(_commentComposite, reactionType); 592 } 593 594 /** 595 * Get parent of comment if exists 596 * @param <T> type of the value to retrieve 597 * @return the comment parent. null if the comment is not a sub comment 598 */ 599 public abstract <T extends AbstractComment> T getCommentParent(); 600 601 /** 602 * Check if the comment is a sub-comment from an other comment 603 * @return true if the comment is a sub-comment 604 */ 605 public boolean isSubComment() 606 { 607 return this.getId().contains(ID_SEPARATOR); 608 } 609 610 /** 611 * Check if the comment have any sub-comments 612 * @return true if the comment have any sub-comments 613 */ 614 public boolean hasSubComments() 615 { 616 return !this.getSubComment(true, true).isEmpty(); 617 } 618 619 /** 620 * Is the comment the accepted answer 621 * @return true if the comment is the accepted answer 622 */ 623 public boolean isAccepted() 624 { 625 return _commentComposite.getValueOfType(METADATA_COMMENT_IS_ACCEPTED, ModelItemTypeConstants.BOOLEAN_TYPE_ID, false); 626 } 627 628 /** 629 * Set the comment as accepted answer. 630 * @param isAccepted true to set the comment as accepted answer. 631 */ 632 public void setAccepted(boolean isAccepted) 633 { 634 _commentComposite.setValue(METADATA_COMMENT_IS_ACCEPTED, isAccepted, ModelItemTypeConstants.BOOLEAN_TYPE_ID); 635 } 636 637}