001package com.box.sdk; 002 003import com.eclipsesource.json.Json; 004import com.eclipsesource.json.JsonObject; 005import com.eclipsesource.json.JsonValue; 006import java.net.URL; 007import java.util.Date; 008import java.util.regex.Pattern; 009 010/** 011 * Represents a comment on a file. Comments can be added directly to a file or they can be created as replies to other 012 * comments. 013 * 014 * <p>Unless otherwise noted, the methods in this class can throw an unchecked {@link BoxAPIException} (unchecked 015 * meaning that the compiler won't force you to handle it) if an error occurs. If you wish to implement custom error 016 * handling for errors related to the Box REST API, you should capture this exception explicitly.</p> 017 */ 018@BoxResourceType("comment") 019public class BoxComment extends BoxResource { 020 021 /** 022 * Add Comment URL Template. 023 */ 024 public static final URLTemplate ADD_COMMENT_URL_TEMPLATE = new URLTemplate("comments"); 025 /** 026 * Comment URL Template. 027 */ 028 public static final URLTemplate COMMENT_URL_TEMPLATE = new URLTemplate("comments/%s"); 029 030 private static final Pattern MENTION_REGEX = Pattern.compile("@\\[.+:.+\\]"); 031 032 /** 033 * Constructs a BoxComment for a comment with a given ID. 034 * 035 * @param api the API connection to be used with the comment. 036 * @param id the ID of the comment. 037 */ 038 public BoxComment(BoxAPIConnection api, String id) { 039 super(api, id); 040 } 041 042 /** 043 * Determines if a comment message contains an @mention. 044 * 045 * @param message the comment message. 046 * @return true if the message contains an @mention; otherwise false. 047 */ 048 static boolean messageContainsMention(String message) { 049 return MENTION_REGEX.matcher(message).find(); 050 } 051 052 /** 053 * Gets information about this comment. 054 * 055 * @return info about this comment. 056 */ 057 public Info getInfo() { 058 URL url = COMMENT_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 059 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET"); 060 BoxJSONResponse response = (BoxJSONResponse) request.send(); 061 JsonObject jsonResponse = Json.parse(response.getJSON()).asObject(); 062 063 return new Info(jsonResponse); 064 } 065 066 /** 067 * Changes the message of this comment. 068 * 069 * @param newMessage the new message for this comment. 070 * @return updated info about this comment. 071 */ 072 public Info changeMessage(String newMessage) { 073 Info newInfo = new Info(); 074 newInfo.setMessage(newMessage); 075 076 URL url = COMMENT_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 077 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "PUT"); 078 request.setBody(newInfo.getPendingChanges()); 079 BoxJSONResponse response = (BoxJSONResponse) request.send(); 080 JsonObject jsonResponse = Json.parse(response.getJSON()).asObject(); 081 082 return new Info(jsonResponse); 083 } 084 085 /** 086 * Replies to this comment with another message. 087 * 088 * @param message the message for the reply. 089 * @return info about the newly created reply comment. 090 */ 091 public BoxComment.Info reply(String message) { 092 JsonObject itemJSON = new JsonObject(); 093 itemJSON.add("type", "comment"); 094 itemJSON.add("id", this.getID()); 095 096 JsonObject requestJSON = new JsonObject(); 097 requestJSON.add("item", itemJSON); 098 if (BoxComment.messageContainsMention(message)) { 099 requestJSON.add("tagged_message", message); 100 } else { 101 requestJSON.add("message", message); 102 } 103 104 URL url = ADD_COMMENT_URL_TEMPLATE.build(this.getAPI().getBaseURL()); 105 BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST"); 106 request.setBody(requestJSON.toString()); 107 BoxJSONResponse response = (BoxJSONResponse) request.send(); 108 JsonObject responseJSON = Json.parse(response.getJSON()).asObject(); 109 110 BoxComment addedComment = new BoxComment(this.getAPI(), responseJSON.get("id").asString()); 111 return addedComment.new Info(responseJSON); 112 } 113 114 /** 115 * Deletes this comment. 116 */ 117 public void delete() { 118 URL url = COMMENT_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID()); 119 BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE"); 120 BoxAPIResponse response = request.send(); 121 response.disconnect(); 122 } 123 124 /** 125 * Contains information about a BoxComment. 126 */ 127 public class Info extends BoxResource.Info { 128 private boolean isReplyComment; 129 private String message; 130 private String taggedMessage; 131 private BoxUser.Info createdBy; 132 private Date createdAt; 133 private BoxResource.Info item; 134 private BoxUser.Info modifiedBy; 135 private Date modifiedAt; 136 137 /** 138 * Constructs an empty Info object. 139 */ 140 public Info() { 141 super(); 142 } 143 144 /** 145 * Constructs an Info object by parsing information from a JSON string. 146 * 147 * @param json the JSON string to parse. 148 */ 149 public Info(String json) { 150 super(json); 151 } 152 153 /** 154 * Constructs an Info object using an already parsed JSON object. 155 * 156 * @param jsonObject the parsed JSON object. 157 */ 158 Info(JsonObject jsonObject) { 159 super(jsonObject); 160 } 161 162 /** 163 * Gets whether or not the comment is a reply to another comment. 164 * 165 * @return true if this comment is a reply to another comment; otherwise false. 166 */ 167 public boolean getIsReplyComment() { 168 return this.isReplyComment; 169 } 170 171 /** 172 * Gets the comment's message. 173 * 174 * @return the comment's message. 175 */ 176 public String getMessage() { 177 if (this.taggedMessage != null) { 178 return this.taggedMessage; 179 } 180 181 return this.message; 182 } 183 184 /** 185 * Sets the comment's message. The message can contain @mentions by using the string @[userid:username] anywhere 186 * within the message, where userid and username are the ID and username of the person being mentioned. 187 * 188 * @param message the comment's new message. 189 */ 190 public void setMessage(String message) { 191 if (messageContainsMention(message)) { 192 this.taggedMessage = message; 193 this.addPendingChange("tagged_message", message); 194 this.removePendingChange("message"); 195 } else { 196 this.message = message; 197 this.addPendingChange("message", message); 198 this.removePendingChange("tagged_message"); 199 } 200 } 201 202 /** 203 * Gets info about the user who created the comment. 204 * 205 * @return info about the user who created the comment. 206 */ 207 public BoxUser.Info getCreatedBy() { 208 return this.createdBy; 209 } 210 211 /** 212 * Gets the time the comment was created. 213 * 214 * @return the time the comment was created. 215 */ 216 public Date getCreatedAt() { 217 return this.createdAt; 218 } 219 220 /** 221 * Gets info about the item this comment is attached to. If the comment is a reply, then the item will be 222 * another BoxComment. Otherwise, the item will be a {@link BoxFile}. 223 * 224 * @return the item this comment is attached to. 225 */ 226 public BoxResource.Info getItem() { 227 return this.item; 228 } 229 230 /** 231 * Gets info about the user who last modified the comment. 232 * 233 * @return info about the user who last modified the comment. 234 */ 235 public BoxUser.Info getModifiedBy() { 236 return this.modifiedBy; 237 } 238 239 /** 240 * Gets the time the comment was last modified. 241 * 242 * @return the time the comment was last modified. 243 */ 244 public Date getModifiedAt() { 245 return this.modifiedAt; 246 } 247 248 @Override 249 public BoxComment getResource() { 250 return BoxComment.this; 251 } 252 253 @Override 254 protected void parseJSONMember(JsonObject.Member member) { 255 super.parseJSONMember(member); 256 String memberName = member.getName(); 257 JsonValue value = member.getValue(); 258 259 try { 260 261 if (memberName.equals("is_reply_comment")) { 262 this.isReplyComment = value.asBoolean(); 263 264 } else if (memberName.equals("message")) { 265 this.message = value.asString(); 266 267 } else if (memberName.equals("tagged_message")) { 268 this.taggedMessage = value.asString(); 269 270 } else if (memberName.equals("created_by")) { 271 JsonObject userJSON = value.asObject(); 272 if (this.createdBy == null) { 273 String userID = userJSON.get("id").asString(); 274 BoxUser user = new BoxUser(getAPI(), userID); 275 this.createdBy = user.new Info(userJSON); 276 } else { 277 this.createdBy.update(userJSON); 278 } 279 280 } else if (memberName.equals("created_at")) { 281 this.createdAt = BoxDateFormat.parse(value.asString()); 282 283 } else if (memberName.equals("item")) { 284 this.parseItem(value); 285 286 } else if (memberName.equals("modified_by")) { 287 JsonObject userJSON = value.asObject(); 288 if (this.modifiedBy == null) { 289 String userID = userJSON.get("id").asString(); 290 BoxUser user = new BoxUser(getAPI(), userID); 291 this.modifiedBy = user.new Info(userJSON); 292 } else { 293 this.modifiedBy.update(userJSON); 294 } 295 } else if (memberName.equals("modified_at")) { 296 this.modifiedAt = BoxDateFormat.parse(value.asString()); 297 } 298 } catch (Exception e) { 299 throw new BoxDeserializationException(memberName, value.toString(), e); 300 } 301 } 302 303 private void parseItem(JsonValue value) { 304 JsonObject itemJSON = value.asObject(); 305 String itemType = itemJSON.get("type").asString(); 306 if (itemType.equals("file")) { 307 this.updateItemAsFile(itemJSON); 308 } else if (itemType.equals("comment")) { 309 this.updateItemAsComment(itemJSON); 310 } 311 } 312 313 private void updateItemAsFile(JsonObject itemJSON) { 314 String itemID = itemJSON.get("id").asString(); 315 if (this.item != null && this.item instanceof BoxFile.Info && this.item.getID().equals(itemID)) { 316 this.item.update(itemJSON); 317 } else { 318 BoxFile file = new BoxFile(getAPI(), itemID); 319 this.item = file.new Info(itemJSON); 320 } 321 } 322 323 private void updateItemAsComment(JsonObject itemJSON) { 324 String itemType = itemJSON.get("type").asString(); 325 String itemID = itemJSON.get("id").asString(); 326 if (this.item != null && this.item instanceof BoxComment.Info && this.item.getID().equals(itemID)) { 327 this.item.update(itemJSON); 328 } else { 329 BoxComment comment = new BoxComment(getAPI(), itemID); 330 this.item = comment.new Info(itemJSON); 331 } 332 } 333 } 334}