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}