Skip to content

Commit 9cbb727

Browse files
authored
feat(endpoint): Added endpoint for Calls
Added a new endpoint to query Calls from a RestComm Connect server. Closes BS-113
1 parent 7c8fc3e commit 9cbb727

File tree

8 files changed

+270
-3
lines changed

8 files changed

+270
-3
lines changed

src/main/java/org/restcomm/sdk/RestcommClient.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package org.restcomm.sdk;
22

3-
import org.restcomm.sdk.domain.Client;
4-
import org.restcomm.sdk.domain.IncomingPhoneNumber;
5-
import org.restcomm.sdk.domain.XmppMapping;
3+
import org.restcomm.sdk.domain.*;
64
import org.restcomm.sdk.endpoints.RestEndpoints;
75

86
import java.util.Map;
@@ -27,6 +25,10 @@ public RestcommClient(RestcommClientConfiguration config) {
2725
this.endpoints = config.getEndpoints();
2826
}
2927

28+
public RestEndpoints<CallPage> getCallsEndpoint() {
29+
return getEndpoints("calls", baseRestcommUrl + "/Calls.json", CallPage.class);
30+
}
31+
3032
public RestEndpoints<Client> getClientsEndpoints() {
3133
return getEndpoints("clients", baseRestcommUrl + "/Clients.json", Client.class);
3234
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package org.restcomm.sdk.domain;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import lombok.Builder;
5+
import lombok.Getter;
6+
import lombok.ToString;
7+
8+
/**
9+
* A Call represents a connection between a phone or user agent and RestComm. This may be inbound or outbound.
10+
* The Calls list resource represents the set of phone calls originated and terminated from an account.
11+
*
12+
* @author Henrique Rosa ([email protected]) created on 21/05/2018
13+
* @see <a href=https://www.restcomm.com/docs/connect/api/calls-api.html#resource-properties>Calls API</a>
14+
*/
15+
@Builder(toBuilder = true)
16+
@Getter
17+
@ToString
18+
public class Call {
19+
20+
private String sid;
21+
private String parentCallSid;
22+
private String dateCreated;
23+
private String dateUpdated;
24+
private String accountSid;
25+
private String from;
26+
private String to;
27+
private String phoneNumberSid;
28+
private String status;
29+
private String startTime;
30+
private String endTime;
31+
private int duration;
32+
private double price;
33+
private String direction;
34+
private String answeredBy;
35+
private String apiVersion;
36+
private String forwardFrom;
37+
private String callerName;
38+
private String uri;
39+
40+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package org.restcomm.sdk.domain;
2+
3+
/**
4+
* Represents the direction of a call.
5+
* <p>
6+
* Possible values are inbound, outbound-api, and outbound-dial.
7+
*
8+
* @author Henrique Rosa ([email protected]) created on 21/05/2018
9+
* @see <a href=https://www.restcomm.com/docs/connect/api/calls-api.html#resource-properties>Call API</a>
10+
*/
11+
public enum CallDirection {
12+
13+
INBOUND("inbound"), OUTBOUND_API("outbound-api"), OUTBOUND_DIAL("outbound-dial");
14+
15+
private final String description;
16+
17+
CallDirection(String description) {
18+
this.description = description;
19+
}
20+
21+
public String description() {
22+
return description;
23+
}
24+
25+
public static CallDirection fromDescription(String description) throws IllegalArgumentException {
26+
for (CallDirection value : values()) {
27+
if (value.description.equalsIgnoreCase(description)) {
28+
return value;
29+
}
30+
}
31+
throw new IllegalArgumentException("No such element matching description: " + description);
32+
}
33+
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package org.restcomm.sdk.domain;
2+
3+
import lombok.Builder;
4+
import lombok.Getter;
5+
import lombok.ToString;
6+
7+
import java.util.List;
8+
9+
/**
10+
* Represents a paginated Calls result.
11+
*
12+
* @author Henrique Rosa ([email protected]) created on 21/05/2018
13+
*
14+
* @see <a href=https://www.restcomm.com/docs/connect/api/calls-api.html#paging-information>Calls API</a>
15+
*/
16+
@Builder(toBuilder = true)
17+
@Getter
18+
@ToString
19+
public class CallPage {
20+
21+
private int page;
22+
private int numPages;
23+
private int pageSize;
24+
private int total;
25+
private int start;
26+
private int end;
27+
private String uri;
28+
private String firstPageUri;
29+
private String previousPageUri;
30+
private String nextPageUri;
31+
private String lastPageUri;
32+
private List<Call> calls;
33+
34+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package org.restcomm.sdk.domain;
2+
3+
/**
4+
* A string representing the status of the call.
5+
* <p>
6+
* Possible values are queued, ringing, in-progress, completed, failed, busy and no-answer.
7+
*
8+
* @author Henrique Rosa ([email protected]) created on 21/05/2018
9+
*/
10+
public enum CallStatus {
11+
12+
QUEUED("queued"), RINGING("ringing"), IN_PROGRESS("in-progress"), COMPLETED("completed"), FAILED("failed"), BUSY("busy"), NO_ANSWER("no-answer");
13+
14+
private final String description;
15+
16+
CallStatus(String description) {
17+
this.description = description;
18+
}
19+
20+
public String description() {
21+
return description;
22+
}
23+
24+
public static CallStatus fromDescription(String description) throws IllegalArgumentException {
25+
for (CallStatus value : values()) {
26+
if (value.description.equalsIgnoreCase(description)) {
27+
return value;
28+
}
29+
}
30+
throw new IllegalArgumentException("No such element matching description: " + description);
31+
}
32+
33+
}

src/main/java/org/restcomm/sdk/endpoints/RestEndpoints.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ public List<T> getAll(Object query) {
2626
.defaultInstance().constructCollectionType(List.class, type));
2727
}
2828

29+
public T get(Object query) {
30+
return httpClient.get(url, query, TypeFactory.defaultInstance().constructType(type));
31+
}
32+
2933
public T create(T entity) {
3034
return httpClient.post(url, entity, type);
3135
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package org.restcomm.sdk.endpoints;
2+
3+
import com.github.tomakehurst.wiremock.junit.WireMockRule;
4+
import org.junit.Rule;
5+
import org.junit.Test;
6+
import org.restcomm.sdk.RestcommClient;
7+
import org.restcomm.sdk.RestcommClientConfiguration;
8+
import org.restcomm.sdk.domain.Call;
9+
import org.restcomm.sdk.domain.CallPage;
10+
import org.restcomm.sdk.domain.CallStatus;
11+
12+
import java.io.File;
13+
import java.io.IOException;
14+
import java.nio.file.Files;
15+
import java.util.Collections;
16+
import java.util.List;
17+
18+
import static com.github.tomakehurst.wiremock.client.WireMock.*;
19+
import static org.junit.Assert.assertEquals;
20+
import static org.junit.Assert.assertNotNull;
21+
22+
/**
23+
* @author Henrique Rosa ([email protected]) created on 22/05/2018
24+
*/
25+
public class CallsEndpointTest {
26+
27+
@Rule
28+
public WireMockRule wireMock = new WireMockRule();
29+
30+
@Test
31+
public void testGetCallPage() throws IOException {
32+
// given
33+
final String username = "username";
34+
final String password = "password";
35+
final String baseUrl = "http://localhost:" + wireMock.port();
36+
final RestcommClient client = new RestcommClient(RestcommClientConfiguration.builder().accountSid(username).accountToken(password).baseUrl(baseUrl).build());
37+
final RestEndpoints<CallPage> callsEndpoint = client.getCallsEndpoint();
38+
39+
final File file = new File("src/test/resources/responses/calls-response.json");
40+
final String response = new String(Files.readAllBytes(file.toPath()));
41+
42+
stubFor(get(urlPathEqualTo("/restcomm/2012-04-24/Accounts/" + username + "/Calls.json"))
43+
.withBasicAuth(username, password)
44+
.willReturn(okJson(response)));
45+
46+
// when
47+
final CallPage callPage = callsEndpoint.get(Collections.emptyMap());
48+
49+
// then
50+
assertNotNull(callPage);
51+
assertEquals(0, callPage.getPage());
52+
assertEquals(50, callPage.getPageSize());
53+
assertEquals(1, callPage.getTotal());
54+
assertEquals(0, callPage.getStart());
55+
assertEquals(1, callPage.getEnd());
56+
assertEquals("/2012-04-24/Accounts/ACa12345/Calls", callPage.getUri());
57+
assertEquals("/2012-04-24/Accounts/ACa12345/Calls?Page\u003d0\u0026PageSize\u003d50", callPage.getFirstPageUri());
58+
assertEquals("null", callPage.getPreviousPageUri());
59+
assertEquals("null", callPage.getNextPageUri());
60+
assertEquals("/2012-04-24/Accounts/ACa12345/Calls?Page\u003d0\u0026PageSize\u003d50", callPage.getLastPageUri());
61+
final List<Call> calls = callPage.getCalls();
62+
assertNotNull(calls);
63+
assertEquals(1, calls.size());
64+
assertEquals("ID12345-CA12345", calls.get(0).getSid());
65+
assertEquals("Fri, 18 May 2018 14:57:59 +0000", calls.get(0).getDateCreated());
66+
assertEquals("Fri, 18 May 2018 14:58:59 +0000", calls.get(0).getDateUpdated());
67+
assertEquals("ACa12345", calls.get(0).getAccountSid());
68+
assertEquals("1708a040dd94e22b04b721b21d", calls.get(0).getTo());
69+
assertEquals("fd5a300f60744d6eb013e06f64da2132", calls.get(0).getFrom());
70+
assertEquals("ACa12345", calls.get(0).getPhoneNumberSid());
71+
assertEquals(CallStatus.FAILED.description(), calls.get(0).getStatus());
72+
assertEquals("2018-05-18T14:57:59.000Z", calls.get(0).getStartTime());
73+
assertEquals("2018-05-18T14:58:59.000Z", calls.get(0).getEndTime());
74+
assertEquals(0, calls.get(0).getDuration());
75+
assertEquals(0.0, calls.get(0).getPrice(), 0);
76+
assertEquals("2012-04-24", calls.get(0).getApiVersion());
77+
assertEquals("Unknown", calls.get(0).getCallerName());
78+
assertEquals("/2012-04-24/Accounts/ACa12345/Calls/ID12345-CA12345.json", calls.get(0).getUri());
79+
}
80+
81+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"page": 0,
3+
"num_pages": 0,
4+
"page_size": 50,
5+
"total": 1,
6+
"start": "0",
7+
"end": "1",
8+
"uri": "/2012-04-24/Accounts/ACa12345/Calls",
9+
"first_page_uri": "/2012-04-24/Accounts/ACa12345/Calls?Page\u003d0\u0026PageSize\u003d50",
10+
"previous_page_uri": "null",
11+
"next_page_uri": "null",
12+
"last_page_uri": "/2012-04-24/Accounts/ACa12345/Calls?Page\u003d0\u0026PageSize\u003d50",
13+
"calls": [
14+
{
15+
"sid": "ID12345-CA12345",
16+
"InstanceId": "ID12345",
17+
"date_created": "Fri, 18 May 2018 14:57:59 +0000",
18+
"date_updated": "Fri, 18 May 2018 14:58:59 +0000",
19+
"account_sid": "ACa12345",
20+
"to": "1708a040dd94e22b04b721b21d",
21+
"from": "fd5a300f60744d6eb013e06f64da2132",
22+
"phone_number_sid": "ACa12345",
23+
"status": "failed",
24+
"start_time": "2018-05-18T14:57:59.000Z",
25+
"end_time": "2018-05-18T14:58:59.000Z",
26+
"duration": 0,
27+
"price": 0.0,
28+
"price_unit": "USD",
29+
"direction": "inbound",
30+
"api_version": "2012-04-24",
31+
"caller_name": "Unknown",
32+
"uri": "/2012-04-24/Accounts/ACa12345/Calls/ID12345-CA12345.json",
33+
"subresource_uris": {
34+
"notifications": "/2012-04-24/Accounts/ACa12345/Calls/ID12345-CA12345/Notifications.json",
35+
"recordings": "/2012-04-24/Accounts/ACa12345/Calls/ID12345-CA12345/Recordings.json"
36+
}
37+
}
38+
]
39+
}

0 commit comments

Comments
 (0)