001/* 002 * Copyright 2024 Vonage 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 */ 016package com.vonage.client.meetings; 017 018import com.fasterxml.jackson.annotation.JsonProperty; 019import com.vonage.client.Jsonable; 020import com.vonage.client.JsonableBaseObject; 021import java.time.Instant; 022import java.time.temporal.ChronoUnit; 023import java.util.UUID; 024 025public class MeetingRoom extends JsonableBaseObject { 026 private Instant createdAt, expiresAt; 027 private UUID id, themeId; 028 private String displayName, metadata, meetingCode; 029 private Boolean isAvailable, expireAfterUse; 030 private RoomType type; 031 private JoinApprovalLevel joinApprovalLevel; 032 private RecordingOptions recordingOptions; 033 private InitialJoinOptions initialJoinOptions; 034 private UISettings uiSettings; 035 private CallbackUrls callbackUrls; 036 private AvailableFeatures availableFeatures; 037 private RoomLinks links; 038 039 protected MeetingRoom() { 040 } 041 042 MeetingRoom(Builder builder) { 043 if ((displayName = builder.displayName) == null || displayName.trim().isEmpty()) { 044 throw new IllegalArgumentException("Display name is required and cannot be empty."); 045 } 046 validateExpiresAtAndRoomType(expiresAt = builder.expiresAt, type = builder.type); 047 if ((expireAfterUse = builder.expireAfterUse) != null && type == RoomType.INSTANT) { 048 throw new IllegalStateException("expireAfterUse is not applicable to "+type+" rooms."); 049 } 050 metadata = builder.metadata; 051 isAvailable = builder.isAvailable; 052 recordingOptions = builder.recordingOptions; 053 initialJoinOptions = builder.initialJoinOptions; 054 callbackUrls = builder.callbackUrls; 055 availableFeatures = builder.availableFeatures; 056 themeId = builder.themeId; 057 joinApprovalLevel = builder.joinApprovalLevel; 058 uiSettings = builder.uiSettings; 059 } 060 061 static void validateExpiresAtAndRoomType(Instant expiresAt, RoomType type) { 062 if (type == RoomType.INSTANT && expiresAt != null) { 063 throw new IllegalStateException("Expiration time should not be specified for "+type+" rooms."); 064 } 065 else if (type == RoomType.LONG_TERM && expiresAt == null) { 066 throw new IllegalStateException("Expiration time must be specified for "+type+" rooms."); 067 } 068 if (expiresAt != null && expiresAt.isBefore(Instant.now().plusSeconds(600))) { 069 throw new IllegalArgumentException("Expiration time should be more than 10 minutes from now."); 070 } 071 } 072 073 /** 074 * Name of the meeting room. 075 * 076 * @return The display name. 077 */ 078 @JsonProperty("display_name") 079 public String getDisplayName() { 080 return displayName; 081 } 082 083 /** 084 * Free text that can be attached to a room. 085 * This will be passed in the form of a header in events related to this room. 086 * 087 * @return The room description / metadata. 088 */ 089 @JsonProperty("metadata") 090 public String getMetadata() { 091 return metadata; 092 } 093 094 /** 095 * The meeting code, which is used in the URL to join the meeting. 096 * 097 * @return The share code for this meeting. 098 */ 099 @JsonProperty("meeting_code") 100 public String getMeetingCode() { 101 return meetingCode; 102 } 103 104 /** 105 * Type of room. 106 * 107 * @return The room type, as an enum. 108 */ 109 @JsonProperty("type") 110 public RoomType getType() { 111 return type; 112 } 113 114 /** 115 * Once a room becomes unavailable, no new sessions can be created under it. 116 * 117 * @return Whether the room is available, or {@code null} if unknown. 118 */ 119 @JsonProperty("is_available") 120 public Boolean getIsAvailable() { 121 return isAvailable; 122 } 123 124 /** 125 * Close the room after a session ends. Only relevant for long_term rooms. 126 * 127 * @return {@code true} if the room will close after end of session, or {@code null} if unknown / not applicable. 128 */ 129 @JsonProperty("expire_after_use") 130 public Boolean getExpireAfterUse() { 131 return expireAfterUse; 132 } 133 134 /** 135 * Options for recording. 136 * 137 * @return The recording options. 138 */ 139 @JsonProperty("recording_options") 140 public RecordingOptions getRecordingOptions() { 141 return recordingOptions; 142 } 143 144 /** 145 * Options for when a participant joins a meeting. 146 * 147 * @return The initial joining options. 148 */ 149 @JsonProperty("initial_join_options") 150 public InitialJoinOptions getInitialJoinOptions() { 151 return initialJoinOptions; 152 } 153 154 /** 155 * Settings for the user interface of this meeting. 156 * 157 * @return The UI settings object. 158 */ 159 @JsonProperty("ui_settings") 160 public UISettings getUiSettings() { 161 return uiSettings; 162 } 163 164 /** 165 * The callback URLs for this meeting. 166 * 167 * @return The CallbackUrls object. 168 */ 169 @JsonProperty("callback_urls") 170 public CallbackUrls getCallbackUrls() { 171 return callbackUrls; 172 } 173 174 /** 175 * The available features for this meeting. 176 * 177 * @return The AvailableFeatures object. 178 */ 179 @JsonProperty("available_features") 180 public AvailableFeatures getAvailableFeatures() { 181 return availableFeatures; 182 } 183 184 /** 185 * ID of the theme for this room. 186 * 187 * @return The theme ID. 188 */ 189 @JsonProperty("theme_id") 190 public UUID getThemeId() { 191 return themeId; 192 } 193 194 /** 195 * The level of approval needed to join the meeting in the room. 196 * 197 * @return The approval level, as an enum. 198 */ 199 @JsonProperty("join_approval_level") 200 public JoinApprovalLevel getJoinApprovalLevel() { 201 return joinApprovalLevel; 202 } 203 204 /** 205 * The time for when the room was created, expressed in ISO 8601 format. 206 * 207 * @return The room creation time. 208 */ 209 @JsonProperty("created_at") 210 public Instant getCreatedAt() { 211 return createdAt; 212 } 213 214 /** 215 * The time for when the room will be expired, expressed in ISO 8601 format. 216 * 217 * @return The room expiration time. 218 */ 219 @JsonProperty("expires_at") 220 public Instant getExpiresAt() { 221 return expiresAt; 222 } 223 224 /** 225 * Identifier of the meeting room. 226 * 227 * @return The room ID. 228 */ 229 @JsonProperty("id") 230 public UUID getId() { 231 return id; 232 } 233 234 /** 235 * Useful links. 236 * 237 * @return The nested links object. 238 */ 239 @JsonProperty("_links") 240 public RoomLinks getLinks() { 241 return links; 242 } 243 244 /** 245 * Creates an instance of this class from a JSON payload. 246 * 247 * @param json The JSON string to parse. 248 * @return An instance of this class with the fields populated, if present. 249 */ 250 public static MeetingRoom fromJson(String json) { 251 return Jsonable.fromJson(json); 252 } 253 254 /** 255 * Entry point for constructing an instance of this class. 256 * 257 * @param displayName Name of the meeting room. 258 * 259 * @return A new Builder. 260 */ 261 public static Builder builder(String displayName) { 262 return new Builder(displayName); 263 } 264 265 public static class Builder { 266 private final String displayName; 267 private UUID themeId; 268 private String metadata; 269 private Instant expiresAt; 270 private Boolean isAvailable, expireAfterUse; 271 private RoomType type; 272 private JoinApprovalLevel joinApprovalLevel; 273 private RecordingOptions recordingOptions; 274 private InitialJoinOptions initialJoinOptions; 275 private UISettings uiSettings; 276 private CallbackUrls callbackUrls; 277 private AvailableFeatures availableFeatures; 278 279 Builder(String displayName) { 280 this.displayName = displayName; 281 } 282 283 /** 284 * Free text that can be attached to a room. This will be passed in the form of a header 285 * in events related to this room. 286 * 287 * @param metadata Additional text / data to be associated with this room. 288 * 289 * @return This builder. 290 */ 291 public Builder metadata(String metadata) { 292 this.metadata = metadata; 293 return this; 294 } 295 296 /** 297 * Type of room. 298 * 299 * @param type The room type. 300 * 301 * @return This builder. 302 */ 303 public Builder type(RoomType type) { 304 this.type = type; 305 return this; 306 } 307 308 /** 309 * Once a room becomes unavailable, no new sessions can be created under it. 310 * 311 * @param isAvailable Whether the room is available. 312 * 313 * @return This builder. 314 */ 315 public Builder isAvailable(boolean isAvailable) { 316 this.isAvailable = isAvailable; 317 return this; 318 } 319 320 /** 321 * Close the room after a session ends. Only relevant for long term rooms. 322 * 323 * @param expireAfterUse Whether the room should close after use. 324 * 325 * @return This builder. 326 */ 327 public Builder expireAfterUse(boolean expireAfterUse) { 328 this.expireAfterUse = expireAfterUse; 329 return this; 330 } 331 332 /** 333 * Options for recording. 334 * 335 * @param recordingOptions The recording options. 336 * 337 * @return This builder. 338 */ 339 public Builder recordingOptions(RecordingOptions recordingOptions) { 340 this.recordingOptions = recordingOptions; 341 return this; 342 } 343 344 /** 345 * Options for when a participant joins a meeting. 346 * 347 * @param initialJoinOptions The initial join options for each participant. 348 * 349 * @return This builder. 350 */ 351 public Builder initialJoinOptions(InitialJoinOptions initialJoinOptions) { 352 this.initialJoinOptions = initialJoinOptions; 353 return this; 354 } 355 356 /** 357 * Settings for the user interface of this meeting. 358 * 359 * @param uiSettings The user interface settings. 360 * 361 * @return This builder. 362 */ 363 public Builder uiSettings(UISettings uiSettings) { 364 this.uiSettings = uiSettings; 365 return this; 366 } 367 368 /** 369 * Callback URLs for this meeting. 370 * 371 * @param callbackUrls The additional URLs for this meeting. 372 * 373 * @return This builder. 374 */ 375 public Builder callbackUrls(CallbackUrls callbackUrls) { 376 this.callbackUrls = callbackUrls; 377 return this; 378 } 379 380 /** 381 * Available features for this meeting. 382 * 383 * @param availableFeatures The features available for this room. 384 * 385 * @return This builder. 386 */ 387 public Builder availableFeatures(AvailableFeatures availableFeatures) { 388 this.availableFeatures = availableFeatures; 389 return this; 390 } 391 392 /** 393 * ID of the theme for this room. 394 * 395 * @param themeId Unique theme identifier. 396 * 397 * @return This builder. 398 */ 399 public Builder themeId(UUID themeId) { 400 this.themeId = themeId; 401 return this; 402 } 403 404 /** 405 * Level of approval needed to join the meeting in the room. 406 * 407 * @param joinApprovalLevel The permission setting for joining this room. 408 * 409 * @return This builder. 410 */ 411 public Builder joinApprovalLevel(JoinApprovalLevel joinApprovalLevel) { 412 this.joinApprovalLevel = joinApprovalLevel; 413 return this; 414 } 415 416 /** 417 * NOTE: This parameter is REQUIRED if the room type is {@link RoomType#LONG_TERM}, 418 * but should not be present if the room type is {@link RoomType#INSTANT}. 419 * 420 * @param expiresAt The time for when the room will expire, expressed in ISO 8601 format. 421 * 422 * @return This builder. 423 */ 424 public Builder expiresAt(Instant expiresAt) { 425 this.expiresAt = expiresAt.truncatedTo(ChronoUnit.MILLIS); 426 return this; 427 } 428 429 430 /** 431 * Builds the {@linkplain MeetingRoom}. 432 * 433 * @return An instance of MeetingRoom, populated with all fields from this builder. 434 */ 435 public MeetingRoom build() { 436 return new MeetingRoom(this); 437 } 438 } 439}