001// Generated by delombok at Thu Aug 13 13:56:44 UTC 2026
002/*
003 * Copyright (c) 2010-2026 Mark Allen, Norbert Bartels.
004 *
005 * Permission is hereby granted, free of charge, to any person obtaining a copy
006 * of this software and associated documentation files (the "Software"), to deal
007 * in the Software without restriction, including without limitation the rights
008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
009 * copies of the Software, and to permit persons to whom the Software is
010 * furnished to do so, subject to the following conditions:
011 *
012 * The above copyright notice and this permission notice shall be included in
013 * all copies or substantial portions of the Software.
014 *
015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
021 * THE SOFTWARE.
022 */
023package com.restfb.types;
024
025import static java.util.Collections.unmodifiableList;
026import java.util.ArrayList;
027import java.util.Date;
028import java.util.List;
029import com.restfb.Facebook;
030import com.restfb.JsonMapper;
031import com.restfb.JsonMapper.JsonMappingCompleted;
032import com.restfb.annotation.GraphAPI;
033import com.restfb.exception.FacebookJsonMappingException;
034import com.restfb.json.JsonObject;
035import com.restfb.types.features.HasComments;
036import com.restfb.types.features.HasCreatedTime;
037import com.restfb.types.features.HasMessage;
038import com.restfb.util.MessageTagUtils;
039
040/**
041 * Represents the <a href="https://developers.facebook.com/docs/graph-api/reference/comment">Comment Graph API type</a>.
042 *
043 * @author <a href="http://restfb.com">Mark Allen</a>
044 * @since 1.5
045 */
046public class Comment extends FacebookType implements HasComments, HasCreatedTime, HasMessage {
047  /**
048   * User who posted the comment.
049   */
050  @Facebook
051  private From from;
052  /**
053   * For a comment made by a page, the page admin who wrote it.
054   */
055  @Facebook("admin_creator")
056  private User adminCreator;
057  /**
058   * The app this comment was published by.
059   */
060  @Facebook
061  private Application application;
062  /**
063   * Text contents of the comment.
064   */
065  @Facebook
066  private String message;
067  /**
068   * Date on which the comment was created.
069   */
070  @Facebook("created_time")
071  private Date createdTime;
072  /**
073   * Duplicate mapping for "likes" since FB can return it differently in different situations.
074   * <p>
075   * -- GETTER -- The likes on this post.
076   * <p>
077   * Sometimes this can be {@code null} - check {@link #getLikeCount()} instead in that case.
078   */
079  @Facebook
080  private Likes likes;
081  /**
082   * The reactions for this post.
083   */
084  @Facebook
085  private Reactions reactions;
086  /**
087   * The number of likes on this comment.
088   *
089   * @since 1.6.10
090   */
091  @Facebook("like_count")
092  private Long likeCount;
093  /**
094   * Number of replies to this comment.
095   */
096  @Facebook("comment_count")
097  private long commentCount;
098  /**
099   * This field is returned only if the authenticated user can remove this comment.
100   *
101   * @since 1.6.10
102   */
103  @Facebook("can_remove")
104  private Boolean canRemove;
105  /**
106   * This field is returned only if the authenticated user likes this comment
107   *
108   * @since 1.6.10
109   */
110  @Facebook("user_likes")
111  private Boolean userLikes;
112  /**
113   * If this comment is a reply, this field returns the parent comment, otherwise no value
114   *
115   * @since 1.6.13
116   */
117  @Facebook
118  private Comment parent;
119  /**
120   * Specifies whether you can reply to this comment
121   *
122   * @since 1.6.13
123   */
124  @Facebook("can_comment")
125  private Boolean canComment;
126  /**
127   * Whether the viewer can hide this comment
128   *
129   * @since 1.7.1
130   */
131  @Facebook("can_hide")
132  private Boolean canHide;
133  /**
134   * Whether the viewer can send a private reply to this comment (Page viewers only)
135   */
136  @Facebook("can_reply_privately")
137  @GraphAPI(since = "2.5")
138  private Boolean canReplyPrivately;
139  /**
140   * For comments with private replies, gets conversation between the Page and author of the comment (Page viewers only)
141   */
142  @Facebook("private_reply_conversation")
143  @GraphAPI(since = "2.5")
144  private Conversation privateReplyConversation;
145  /**
146   * Whether this comment is hidden. The original poster can still see the comment, along with the page admin and anyone
147   * else tagged in the comment
148   *
149   * @since 1.7.1
150   */
151  @Facebook("is_hidden")
152  private Boolean isHidden;
153  /**
154   * Whether the comment is a private comment.
155   */
156  @Facebook("is_private")
157  private Boolean isPrivate;
158  /**
159   * Whether the viewer can like this comment
160   */
161  @Facebook("can_like")
162  private Boolean canLike;
163  /**
164   * Parent object this comment was made on.
165   *
166   * @since 1.7.1
167   */
168  @Facebook
169  private NamedFacebookType object;
170  /**
171   * The permanent static URL to the comment
172   */
173  @Facebook("permalink_url")
174  private String permalinkUrl;
175  /**
176   * Time the comment was made on a live video.
177   */
178  @Facebook("live_broadcast_timestamp")
179  private Date liveBroadcastTimestamp;
180  /**
181   * The replies to this comment
182   */
183  @Facebook("comments")
184  private Comments comments;
185  /**
186   * Attachment (image) added to a comment.
187   * <p>
188   * To force Facebook to fill the <code>attachment</code> field you have to fetch the comment with the
189   * <code>fields=attachment</code> parameter, otherwise the attachments are <code>null</code>.
190   */
191  @Facebook
192  private StoryAttachment attachment;
193  @Facebook("message_tags")
194  private transient String rawMessageTags;
195  private List<MessageTag> messageTags = new ArrayList<>();
196  private static final long serialVersionUID = 2L;
197
198  /**
199   * Post-JSON-mapping operation that populates the {@code messageTags} field "by hand".
200   *
201   * @param jsonMapper
202   *          The {@code JsonMapper} that was used to map to this type.
203   */
204  @JsonMappingCompleted
205  protected void jsonMappingCompleted(JsonMapper jsonMapper) {
206    if (rawMessageTags == null) {
207      return;
208    }
209    try {
210      messageTags = jsonMapper.toJavaList(rawMessageTags, MessageTag.class);
211      return;
212    } catch (FacebookJsonMappingException je) {
213    }
214    // message tags not in Graph API 2.5 format, ignore this exception and try another way
215    try {
216      JsonObject rawMessageTagsObject = jsonMapper.toJavaObject(rawMessageTags, JsonObject.class);
217      for (String key : rawMessageTagsObject.names()) {
218        String tagArrayString = rawMessageTagsObject.get(key).toString();
219        messageTags.addAll(jsonMapper.toJavaList(tagArrayString, MessageTag.class));
220      }
221    } catch (FacebookJsonMappingException je) {
222    }
223    // cannot parse message tags, but don't break the flow here
224  }
225
226  /**
227   * Objects tagged in the message (Users, Pages, etc.)
228   *
229   * @return Objects tagged in the message (Users, Pages, etc.)
230   * @since 1.6.10
231   */
232  public List<MessageTag> getMessageTags() {
233    return unmodifiableList(messageTags);
234  }
235
236  public void addMessageTag(MessageTag messageTag) {
237    messageTags.add(messageTag);
238  }
239
240  public void removeMessageTag(MessageTag messageTag) {
241    messageTags.remove(messageTag);
242  }
243
244  /**
245   * Returns the {@link #getMessage() message} where tagged segments have been replaced with their mention syntax.
246   *
247   * @return normalized message text or the original message if it cannot be normalized
248   */
249  public String getNormalizedMessage() {
250    return MessageTagUtils.normalizeMessage(message, messageTags);
251  }
252
253  /**
254   * User who posted the comment.
255   *
256   * @return User who posted the comment.
257   */
258  @java.lang.SuppressWarnings("all")
259  @lombok.Generated
260  public From getFrom() {
261    return this.from;
262  }
263
264  /**
265   * User who posted the comment.
266   */
267  @java.lang.SuppressWarnings("all")
268  @lombok.Generated
269  public void setFrom(final From from) {
270    this.from = from;
271  }
272
273  /**
274   * For a comment made by a page, the page admin who wrote it.
275   *
276   * @return the page admin who wrote the comment.
277   */
278  @java.lang.SuppressWarnings("all")
279  @lombok.Generated
280  public User getAdminCreator() {
281    return this.adminCreator;
282  }
283
284  /**
285   * For a comment made by a page, the page admin who wrote it.
286   */
287  @java.lang.SuppressWarnings("all")
288  @lombok.Generated
289  public void setAdminCreator(final User adminCreator) {
290    this.adminCreator = adminCreator;
291  }
292
293  /**
294   * The app this comment was published by.
295   *
296   * @return the app this comment was published by.
297   */
298  @java.lang.SuppressWarnings("all")
299  @lombok.Generated
300  public Application getApplication() {
301    return this.application;
302  }
303
304  /**
305   * The app this comment was published by.
306   */
307  @java.lang.SuppressWarnings("all")
308  @lombok.Generated
309  public void setApplication(final Application application) {
310    this.application = application;
311  }
312
313  /**
314   * Text contents of the comment.
315   *
316   * @return Text contents of the comment.
317   */
318  @Override
319  @java.lang.SuppressWarnings("all")
320  @lombok.Generated
321  public String getMessage() {
322    return this.message;
323  }
324
325  /**
326   * Text contents of the comment.
327   */
328  @java.lang.SuppressWarnings("all")
329  @lombok.Generated
330  public void setMessage(final String message) {
331    this.message = message;
332  }
333
334  /**
335   * Date on which the comment was created.
336   *
337   * @return Date on which the comment was created.
338   */
339  @Override
340  @java.lang.SuppressWarnings("all")
341  @lombok.Generated
342  public Date getCreatedTime() {
343    return this.createdTime;
344  }
345
346  /**
347   * Date on which the comment was created.
348   */
349  @java.lang.SuppressWarnings("all")
350  @lombok.Generated
351  public void setCreatedTime(final Date createdTime) {
352    this.createdTime = createdTime;
353  }
354
355  /**
356   * Duplicate mapping for "likes" since FB can return it differently in different situations.
357   * <p>
358   * -- GETTER -- The likes on this post.
359   * <p>
360   * Sometimes this can be {@code null} - check {@link #getLikeCount()} instead in that case.
361   *
362   * @return The likes on this comment.
363   */
364  @java.lang.SuppressWarnings("all")
365  @lombok.Generated
366  public Likes getLikes() {
367    return this.likes;
368  }
369
370  /**
371   * Duplicate mapping for "likes" since FB can return it differently in different situations.
372   * <p>
373   * -- GETTER -- The likes on this post.
374   * <p>
375   * Sometimes this can be {@code null} - check {@link #getLikeCount()} instead in that case.
376   */
377  @java.lang.SuppressWarnings("all")
378  @lombok.Generated
379  public void setLikes(final Likes likes) {
380    this.likes = likes;
381  }
382
383  /**
384   * The reactions for this post.
385   *
386   * @return The reactions for this post.
387   */
388  @java.lang.SuppressWarnings("all")
389  @lombok.Generated
390  public Reactions getReactions() {
391    return this.reactions;
392  }
393
394  /**
395   * The reactions for this post.
396   */
397  @java.lang.SuppressWarnings("all")
398  @lombok.Generated
399  public void setReactions(final Reactions reactions) {
400    this.reactions = reactions;
401  }
402
403  /**
404   * The number of likes on this comment.
405   *
406   * @return The number of likes on this comment.
407   * @since 1.6.10
408   */
409  @java.lang.SuppressWarnings("all")
410  @lombok.Generated
411  public Long getLikeCount() {
412    return this.likeCount;
413  }
414
415  /**
416   * The number of likes on this comment.
417   *
418   * @since 1.6.10
419   */
420  @java.lang.SuppressWarnings("all")
421  @lombok.Generated
422  public void setLikeCount(final Long likeCount) {
423    this.likeCount = likeCount;
424  }
425
426  /**
427   * Number of replies to this comment.
428   *
429   * @return Number of replies to this comment
430   */
431  @java.lang.SuppressWarnings("all")
432  @lombok.Generated
433  public long getCommentCount() {
434    return this.commentCount;
435  }
436
437  /**
438   * Number of replies to this comment.
439   */
440  @java.lang.SuppressWarnings("all")
441  @lombok.Generated
442  public void setCommentCount(final long commentCount) {
443    this.commentCount = commentCount;
444  }
445
446  /**
447   * This field is returned only if the authenticated user can remove this comment.
448   *
449   * @return This field is returned only if the authenticated user can remove this comment.
450   * @since 1.6.10
451   */
452  @java.lang.SuppressWarnings("all")
453  @lombok.Generated
454  public Boolean getCanRemove() {
455    return this.canRemove;
456  }
457
458  /**
459   * This field is returned only if the authenticated user can remove this comment.
460   *
461   * @since 1.6.10
462   */
463  @java.lang.SuppressWarnings("all")
464  @lombok.Generated
465  public void setCanRemove(final Boolean canRemove) {
466    this.canRemove = canRemove;
467  }
468
469  /**
470   * This field is returned only if the authenticated user likes this comment
471   *
472   * @return This field is returned only if the authenticated user likes this comment.
473   * @since 1.6.10
474   */
475  @java.lang.SuppressWarnings("all")
476  @lombok.Generated
477  public Boolean getUserLikes() {
478    return this.userLikes;
479  }
480
481  /**
482   * This field is returned only if the authenticated user likes this comment
483   *
484   * @since 1.6.10
485   */
486  @java.lang.SuppressWarnings("all")
487  @lombok.Generated
488  public void setUserLikes(final Boolean userLikes) {
489    this.userLikes = userLikes;
490  }
491
492  /**
493   * If this comment is a reply, this field returns the parent comment, otherwise no value
494   *
495   * @return the parent Comment
496   * @since 1.6.13
497   */
498  @java.lang.SuppressWarnings("all")
499  @lombok.Generated
500  public Comment getParent() {
501    return this.parent;
502  }
503
504  /**
505   * If this comment is a reply, this field returns the parent comment, otherwise no value
506   *
507   * @since 1.6.13
508   */
509  @java.lang.SuppressWarnings("all")
510  @lombok.Generated
511  public void setParent(final Comment parent) {
512    this.parent = parent;
513  }
514
515  /**
516   * Specifies whether you can reply to this comment
517   *
518   * @return can_comment
519   * @since 1.6.13
520   */
521  @java.lang.SuppressWarnings("all")
522  @lombok.Generated
523  public Boolean getCanComment() {
524    return this.canComment;
525  }
526
527  /**
528   * Specifies whether you can reply to this comment
529   *
530   * @since 1.6.13
531   */
532  @java.lang.SuppressWarnings("all")
533  @lombok.Generated
534  public void setCanComment(final Boolean canComment) {
535    this.canComment = canComment;
536  }
537
538  /**
539   * Whether the viewer can hide this comment
540   *
541   * @return can_hide
542   * @since 1.7.1
543   */
544  @java.lang.SuppressWarnings("all")
545  @lombok.Generated
546  public Boolean getCanHide() {
547    return this.canHide;
548  }
549
550  /**
551   * Whether the viewer can hide this comment
552   *
553   * @since 1.7.1
554   */
555  @java.lang.SuppressWarnings("all")
556  @lombok.Generated
557  public void setCanHide(final Boolean canHide) {
558    this.canHide = canHide;
559  }
560
561  /**
562   * Whether the viewer can send a private reply to this comment (Page viewers only)
563   *
564   * @return Whether the viewer can send a private reply to this comment
565   */
566  @GraphAPI(since = "2.5")
567  @java.lang.SuppressWarnings("all")
568  @lombok.Generated
569  public Boolean getCanReplyPrivately() {
570    return this.canReplyPrivately;
571  }
572
573  /**
574   * Whether the viewer can send a private reply to this comment (Page viewers only)
575   */
576  @java.lang.SuppressWarnings("all")
577  @lombok.Generated
578  public void setCanReplyPrivately(final Boolean canReplyPrivately) {
579    this.canReplyPrivately = canReplyPrivately;
580  }
581
582  /**
583   * For comments with private replies, gets conversation between the Page and author of the comment (Page viewers only)
584   *
585   * @return conversation between Page and author of the comment
586   */
587  @GraphAPI(since = "2.5")
588  @java.lang.SuppressWarnings("all")
589  @lombok.Generated
590  public Conversation getPrivateReplyConversation() {
591    return this.privateReplyConversation;
592  }
593
594  /**
595   * For comments with private replies, gets conversation between the Page and author of the comment (Page viewers only)
596   */
597  @java.lang.SuppressWarnings("all")
598  @lombok.Generated
599  public void setPrivateReplyConversation(final Conversation privateReplyConversation) {
600    this.privateReplyConversation = privateReplyConversation;
601  }
602
603  /**
604   * Whether this comment is hidden. The original poster can still see the comment, along with the page admin and anyone
605   * else tagged in the comment
606   *
607   * @return is_hidden
608   * @since 1.7.1
609   */
610  @java.lang.SuppressWarnings("all")
611  @lombok.Generated
612  public Boolean getIsHidden() {
613    return this.isHidden;
614  }
615
616  /**
617   * Whether this comment is hidden. The original poster can still see the comment, along with the page admin and anyone
618   * else tagged in the comment
619   *
620   * @since 1.7.1
621   */
622  @java.lang.SuppressWarnings("all")
623  @lombok.Generated
624  public void setIsHidden(final Boolean isHidden) {
625    this.isHidden = isHidden;
626  }
627
628  /**
629   * Whether the comment is a private comment.
630   *
631   * @return is_private
632   */
633  @java.lang.SuppressWarnings("all")
634  @lombok.Generated
635  public Boolean getIsPrivate() {
636    return this.isPrivate;
637  }
638
639  /**
640   * Whether the comment is a private comment.
641   */
642  @java.lang.SuppressWarnings("all")
643  @lombok.Generated
644  public void setIsPrivate(final Boolean isPrivate) {
645    this.isPrivate = isPrivate;
646  }
647
648  /**
649   * Whether the viewer can like this comment
650   *
651   * @return can_like
652   */
653  @java.lang.SuppressWarnings("all")
654  @lombok.Generated
655  public Boolean getCanLike() {
656    return this.canLike;
657  }
658
659  /**
660   * Whether the viewer can like this comment
661   */
662  @java.lang.SuppressWarnings("all")
663  @lombok.Generated
664  public void setCanLike(final Boolean canLike) {
665    this.canLike = canLike;
666  }
667
668  /**
669   * Parent object this comment was made on.
670   *
671   * @return object
672   * @since 1.7.1
673   */
674  @java.lang.SuppressWarnings("all")
675  @lombok.Generated
676  public NamedFacebookType getObject() {
677    return this.object;
678  }
679
680  /**
681   * Parent object this comment was made on.
682   *
683   * @since 1.7.1
684   */
685  @java.lang.SuppressWarnings("all")
686  @lombok.Generated
687  public void setObject(final NamedFacebookType object) {
688    this.object = object;
689  }
690
691  /**
692   * The permanent static URL to the comment
693   *
694   * @return permanent static url
695   */
696  @java.lang.SuppressWarnings("all")
697  @lombok.Generated
698  public String getPermalinkUrl() {
699    return this.permalinkUrl;
700  }
701
702  /**
703   * The permanent static URL to the comment
704   */
705  @java.lang.SuppressWarnings("all")
706  @lombok.Generated
707  public void setPermalinkUrl(final String permalinkUrl) {
708    this.permalinkUrl = permalinkUrl;
709  }
710
711  /**
712   * Time the comment was made on a live video.
713   *
714   * @return live_broadcast_timestamp
715   */
716  @java.lang.SuppressWarnings("all")
717  @lombok.Generated
718  public Date getLiveBroadcastTimestamp() {
719    return this.liveBroadcastTimestamp;
720  }
721
722  /**
723   * Time the comment was made on a live video.
724   */
725  @java.lang.SuppressWarnings("all")
726  @lombok.Generated
727  public void setLiveBroadcastTimestamp(final Date liveBroadcastTimestamp) {
728    this.liveBroadcastTimestamp = liveBroadcastTimestamp;
729  }
730
731  /**
732   * The replies to this comment
733   *
734   * @return replies
735   */
736  @Override
737  @java.lang.SuppressWarnings("all")
738  @lombok.Generated
739  public Comments getComments() {
740    return this.comments;
741  }
742
743  /**
744   * The replies to this comment
745   */
746  @java.lang.SuppressWarnings("all")
747  @lombok.Generated
748  public void setComments(final Comments comments) {
749    this.comments = comments;
750  }
751
752  /**
753   * Attachment (image) added to a comment.
754   * <p>
755   * To force Facebook to fill the <code>attachment</code> field you have to fetch the comment with the
756   * <code>fields=attachment</code> parameter, otherwise the attachments are <code>null</code>.
757   *
758   * @return Attachment on the comment
759   */
760  @java.lang.SuppressWarnings("all")
761  @lombok.Generated
762  public StoryAttachment getAttachment() {
763    return this.attachment;
764  }
765
766  /**
767   * Attachment (image) added to a comment.
768   * <p>
769   * To force Facebook to fill the <code>attachment</code> field you have to fetch the comment with the
770   * <code>fields=attachment</code> parameter, otherwise the attachments are <code>null</code>.
771   */
772  @java.lang.SuppressWarnings("all")
773  @lombok.Generated
774  public void setAttachment(final StoryAttachment attachment) {
775    this.attachment = attachment;
776  }
777}