Skip to content

Commit

Permalink
refactor: DynamicEndpoint for Video API
Browse files Browse the repository at this point in the history
  • Loading branch information
SMadani committed Dec 21, 2023
1 parent 1d3f62c commit d5ca25b
Show file tree
Hide file tree
Showing 7 changed files with 1,294 additions and 185 deletions.
80 changes: 80 additions & 0 deletions src/main/java/com/vonage/client/video/MuteSessionResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright 2023 Vonage
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.vonage.client.video;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.vonage.client.Jsonable;

@JsonIgnoreProperties(ignoreUnknown = true)
public class MuteSessionResponse implements Jsonable {
private String applicationId, name;
private ProjectStatus status;
private ProjectEnvironment environment;
private Long createdAt;

protected MuteSessionResponse() {
}

/**
*
* @return The Vonage application ID.
*/
public String getApplicationId() {
return applicationId;
}

/**
*
* @return Whether the project is active or suspended.
*/
public ProjectStatus getStatus() {
return status;
}

/**
*
* @return The project name, if specified when created.
*/
public String getName() {
return name;
}

/**
*
* @return The environment the project is running on.
*/
public ProjectEnvironment getEnvironment() {
return environment;
}

/**
*
* @return The time at which the project was created (a UNIX timestamp, in milliseconds).
*/
public Long getCreatedAt() {
return createdAt;
}

/**
* Creates an instance of this class from a JSON payload.
*
* @param json The JSON string to parse.
* @return An instance of this class with the fields populated, if present.
*/
public static MuteSessionResponse fromJson(String json) {
return Jsonable.fromJson(json, MuteSessionResponse.class);
}
}
83 changes: 53 additions & 30 deletions src/main/java/com/vonage/client/video/VideoClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@
*/
package com.vonage.client.video;

import com.vonage.client.DynamicEndpoint;
import com.vonage.client.HttpWrapper;
import com.vonage.client.RestEndpoint;
import com.vonage.client.VonageClient;
import com.vonage.client.auth.JWTAuthMethod;
import com.vonage.client.auth.TokenAuthMethod;
import com.vonage.client.common.HttpMethod;
import com.vonage.jwt.Jwt;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;

/**
Expand All @@ -39,7 +43,7 @@ public class VideoClient {
final RestEndpoint<SetStreamLayoutRequest, Void> setStreamLayout;
final RestEndpoint<SignalRequest, Void> signal, signalAll;
final RestEndpoint<SessionResourceRequestWrapper, Void> forceDisconnect, muteStream;
final RestEndpoint<MuteSessionRequest, Void> muteSession;
final RestEndpoint<MuteSessionRequest, MuteSessionResponse> muteSession;
final RestEndpoint<SipDialRequest, SipDialResponse> sipDial;
final RestEndpoint<SendDtmfRequest, Void> sendDtmfToSession, sendDtmfToConnection;
final RestEndpoint<ListStreamCompositionsRequest, ListArchivesResponse> listArchives;
Expand All @@ -55,35 +59,54 @@ public class VideoClient {
/**
* Constructor.
*
* @param httpWrapper (REQUIRED) shared HTTP wrapper object used for making REST calls.
*/
public VideoClient(final HttpWrapper httpWrapper) {
newJwtSupplier = () -> httpWrapper.getAuthCollection().getAuth(JWTAuthMethod.class).newJwt();
createSession = new CreateSessionEndpoint(httpWrapper);
listStreams = new ListStreamsEndpoint(httpWrapper);
getStream = new GetStreamEndpoint(httpWrapper);
setStreamLayout = new SetStreamLayoutEndpoint(httpWrapper);
signalAll = new SignalAllEndpoint(httpWrapper);
signal = new SignalEndpoint(httpWrapper);
forceDisconnect = new ForceDisconnectEndpoint(httpWrapper);
muteStream = new MuteStreamEndpoint(httpWrapper);
muteSession = new MuteSessionEndpoint(httpWrapper);
sipDial = new SipDialEndpoint(httpWrapper);
sendDtmfToSession = new SendDtmfToSessionEndpoint(httpWrapper);
sendDtmfToConnection = new SendDtmfToConnectionEndpoint(httpWrapper);
listArchives = new ListArchivesEndpoint(httpWrapper);
getArchive = new GetArchiveEndpoint(httpWrapper);
createArchive = new CreateArchiveEndpoint(httpWrapper);
updateArchiveLayout = new UpdateArchiveLayoutEndpoint(httpWrapper);
patchArchiveStream = new PatchArchiveStreamEndpoint(httpWrapper);
stopArchive = new StopArchiveEndpoint(httpWrapper);
deleteArchive = new DeleteArchiveEndpoint(httpWrapper);
listBroadcasts = new ListBroadcastsEndpoint(httpWrapper);
getBroadcast = new GetBroadcastEndpoint(httpWrapper);
createBroadcast = new CreateBroadcastEndpoint(httpWrapper);
updateBroadcastLayout = new UpdateBroadcastLayoutEndpoint(httpWrapper);
patchBroadcastStream = new PatchBroadcastStreamEndpoint(httpWrapper);
stopBroadcast = new StopBroadcastEndpoint(httpWrapper);
* @param wrapper (REQUIRED) shared HTTP wrapper object used for making REST calls.
*/
public VideoClient(HttpWrapper wrapper) {
Supplier<JWTAuthMethod> jwtAuthGetter = () -> wrapper.getAuthCollection().getAuth(JWTAuthMethod.class);
Supplier<String> appIdGetter = () -> jwtAuthGetter.get().getApplicationId();
newJwtSupplier = () -> jwtAuthGetter.get().newJwt();

@SuppressWarnings("unchecked")
class Endpoint<T, R> extends DynamicEndpoint<T, R> {
Endpoint(Function<T, String> pathGetter, HttpMethod method, R... type) {
super(DynamicEndpoint.<T, R> builder(type)
.authMethod(JWTAuthMethod.class, TokenAuthMethod.class)
.responseExceptionType(VideoResponseException.class)
.requestMethod(method).wrapper(wrapper).pathGetter((de, req) -> {
String base = de.getHttpWrapper().getHttpConfig().getVideoBaseUri();
String end = pathGetter.apply(req);
String mid = end.startsWith("/") ? "" : "/v2/project/" + appIdGetter.get() + "/";
return base + mid + end;
})
);
}
}

createSession = new Endpoint<>(req -> "/session/create", HttpMethod.POST);
listStreams = new Endpoint<>(req -> "session/"+req+"/stream", HttpMethod.GET);
setStreamLayout = new Endpoint<>(req -> "session/"+req.sessionId+"/stream", HttpMethod.PUT);
getStream = new Endpoint<>(req -> "session/"+req.sessionId+"/stream/"+req.resourceId, HttpMethod.GET);
signalAll = new Endpoint<>(req -> "session/"+req.sessionId+"/signal", HttpMethod.POST);
signal = new Endpoint<>(req -> "session/"+req.sessionId+"/connection/"+req.connectionId+"/signal", HttpMethod.POST);
forceDisconnect = new Endpoint<>(req -> "session/"+req.sessionId+"/connection/"+req.resourceId, HttpMethod.DELETE);
muteStream = new Endpoint<>(req -> "session/"+req.sessionId+"/stream/"+req.resourceId+"/mute", HttpMethod.POST);
muteSession = new Endpoint<>(req -> "session/"+req.sessionId+"/mute", HttpMethod.POST);
updateArchiveLayout = new Endpoint<>(req -> "archive/"+req.id+"/layout", HttpMethod.PUT);
deleteArchive = new Endpoint<>(req -> "archive/"+req, HttpMethod.DELETE);
patchArchiveStream = new Endpoint<>(req -> "archive/"+req.id+"/streams", HttpMethod.PATCH);
stopArchive = new Endpoint<>(req -> "archive/"+req+"/stop", HttpMethod.POST);
createArchive = new Endpoint<>(req -> "archive", HttpMethod.POST);
listArchives = new Endpoint<>(req -> "archive", HttpMethod.GET);
getArchive = new Endpoint<>(req -> "archive/"+req, HttpMethod.GET);
sendDtmfToConnection = new Endpoint<>(req -> "session/"+req.sessionId+"/connection/"+req.connectionId+"/play-dtmf", HttpMethod.POST);
sendDtmfToSession = new Endpoint<>(req -> "session/"+req.sessionId+"/play-dtmf", HttpMethod.POST);
listBroadcasts = new Endpoint<>(req -> "broadcast", HttpMethod.GET);
createBroadcast = new Endpoint<>(req -> "broadcast", HttpMethod.POST);
getBroadcast = new Endpoint<>(req -> "broadcast/"+req, HttpMethod.GET);
stopBroadcast = new Endpoint<>(req -> "broadcast/"+req+"/stop", HttpMethod.POST);
updateBroadcastLayout = new Endpoint<>(req -> "broadcast/"+req.id+"/layout", HttpMethod.POST);
patchBroadcastStream = new Endpoint<>(req -> "broadcast/"+req.id+"/streams", HttpMethod.PATCH);
sipDial = new Endpoint<>(req -> "dial", HttpMethod.POST);
}

private String validateId(String param, String name, boolean uuid) {
Expand Down
45 changes: 45 additions & 0 deletions src/main/java/com/vonage/client/video/VideoResponseException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2023 Vonage
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.vonage.client.video;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.vonage.client.Jsonable;
import com.vonage.client.VonageApiResponseException;

/**
* Response returned when an error is encountered (i.e. the API returns a non-2xx status code).
*/
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public final class VideoResponseException extends VonageApiResponseException {

void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}

/**
* Creates an instance of this class from a JSON payload.
*
* @param json The JSON string to parse.
* @return An instance of this class with all known fields populated from the JSON payload, if present.
*/
@JsonCreator
public static VideoResponseException fromJson(String json) {
return Jsonable.fromJson(json);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,24 +45,24 @@ public void testMakeRequestAllParameters() throws Exception {
ListStreamCompositionsRequest request = ListStreamCompositionsRequest.builder()
.offset(6).count(25).sessionId("SESSION_ID").build();
RequestBuilder builder = endpoint.makeRequest(request);
Assertions.assertEquals("GET", builder.getMethod());
assertEquals("GET", builder.getMethod());
String expectedUri = "https://video.api.vonage.com/v2/project/"+applicationId +
"/broadcast?offset=6&count=25&sessionId=SESSION_ID";
Assertions.assertEquals(expectedUri, builder.build().getURI().toString());
Assertions.assertEquals(ContentType.APPLICATION_JSON.getMimeType(), builder.getFirstHeader("Accept").getValue());
assertEquals(expectedUri, builder.build().getURI().toString());
assertEquals(ContentType.APPLICATION_JSON.getMimeType(), builder.getFirstHeader("Accept").getValue());
Map<String, String> params = TestUtils.makeParameterMap(builder.getParameters());
Assertions.assertEquals(3, params.size());
Assertions.assertEquals(request.getOffset().toString(), params.get("offset"));
Assertions.assertEquals(request.getCount().toString(), params.get("count"));
Assertions.assertEquals(request.getSessionId(), params.get("sessionId"));
assertEquals(3, params.size());
assertEquals(request.getOffset().toString(), params.get("offset"));
assertEquals(request.getCount().toString(), params.get("count"));
assertEquals(request.getSessionId(), params.get("sessionId"));
String expectedResponse = "{\"count\":2,\"items\":[{},{\"applicationId\":\""+applicationId+"\"}]}";
HttpResponse mockResponse = TestUtils.makeJsonHttpResponse(200, expectedResponse);
ListBroadcastsResponse parsed = endpoint.parseResponse(mockResponse);
Assertions.assertNotNull(parsed);
Assertions.assertEquals(2, parsed.getCount().intValue());
Assertions.assertEquals(2, parsed.getItems().size());
Assertions.assertNotNull(parsed.getItems().get(0));
Assertions.assertEquals(applicationId, parsed.getItems().get(1).getApplicationId().toString());
assertNotNull(parsed);
assertEquals(2, parsed.getCount().intValue());
assertEquals(2, parsed.getItems().size());
assertNotNull(parsed.getItems().get(0));
assertEquals(applicationId, parsed.getItems().get(1).getApplicationId().toString());
}

@Test
Expand All @@ -76,11 +76,11 @@ public void testCustomUri() throws Exception {
String expectedUri = baseUri + "/v2/project/"+applicationId+"/broadcast";
ListStreamCompositionsRequest request = ListStreamCompositionsRequest.builder().build();
RequestBuilder builder = endpoint.makeRequest(request);
Assertions.assertEquals(expectedUri, builder.build().getURI().toString());
Assertions.assertEquals(ContentType.APPLICATION_JSON.getMimeType(), builder.getFirstHeader("Accept").getValue());
Assertions.assertEquals("GET", builder.getMethod());
assertEquals(expectedUri, builder.build().getURI().toString());
assertEquals(ContentType.APPLICATION_JSON.getMimeType(), builder.getFirstHeader("Accept").getValue());
assertEquals("GET", builder.getMethod());
Map<String, String> params = TestUtils.makeParameterMap(builder.getParameters());
Assertions.assertEquals(0, params.size());
assertEquals(0, params.size());
}

@Test
Expand Down
20 changes: 10 additions & 10 deletions src/test/java/com/vonage/client/video/ListStreamsEndpointTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ public void setUp() {
public void testMakeRequestAllParameters() throws Exception {
String sessionId = UUID.randomUUID().toString();
RequestBuilder builder = endpoint.makeRequest(sessionId);
Assertions.assertEquals("GET", builder.getMethod());
assertEquals("GET", builder.getMethod());
String expectedUri = "https://video.api.vonage.com/v2/project/"+applicationId+"/session/"+sessionId+"/stream";
Assertions.assertEquals(expectedUri, builder.build().getURI().toString());
Assertions.assertEquals(ContentType.APPLICATION_JSON.getMimeType(), builder.getFirstHeader("Accept").getValue());
assertEquals(expectedUri, builder.build().getURI().toString());
assertEquals(ContentType.APPLICATION_JSON.getMimeType(), builder.getFirstHeader("Accept").getValue());
}

@Test
Expand All @@ -72,16 +72,16 @@ public void testParseValidResponse() throws Exception {

HttpResponse mockHttpResponse = TestUtils.makeJsonHttpResponse(200, json);
ListStreamsResponse response = endpoint.parseResponse(mockHttpResponse);
Assertions.assertEquals(count, response.getCount());
assertEquals(count, response.getCount());
List<GetStreamResponse> streams = response.getItems();
Assertions.assertEquals(1, streams.size());
assertEquals(1, streams.size());
GetStreamResponse stream0 = streams.get(0);
Assertions.assertEquals(id0, stream0.getId());
Assertions.assertEquals(videoType0, stream0.getVideoType());
Assertions.assertEquals(name0, stream0.getName());
assertEquals(id0, stream0.getId());
assertEquals(videoType0, stream0.getVideoType());
assertEquals(name0, stream0.getName());
List<String> layoutClassList0 = stream0.getLayoutClassList();
Assertions.assertEquals(1, layoutClassList0.size());
Assertions.assertEquals(layoutClass0, layoutClassList0.get(0));
assertEquals(1, layoutClassList0.size());
assertEquals(layoutClass0, layoutClassList0.get(0));
}

@Test
Expand Down
Loading

0 comments on commit d5ca25b

Please sign in to comment.