From 315875490d17e5d82fc8b5198b5727d70c3009ba Mon Sep 17 00:00:00 2001 From: Steve Crow Date: Mon, 17 Sep 2018 10:45:12 -0400 Subject: [PATCH 1/8] IntelliJ still sometimes uses the out folder even when told not to. --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 38c0be49e..a336d3317 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,5 @@ nexmo-sdk.jar publishing valid_application_key.pem /.idea -*.iml \ No newline at end of file +*.iml +out/ \ No newline at end of file From c9dfff950cdbd9214bf6fc06a50e2799f49d7ed6 Mon Sep 17 00:00:00 2001 From: Steve Crow Date: Wed, 19 Sep 2018 10:12:42 -0400 Subject: [PATCH 2/8] Add Java version to user agent. (#188) --- CHANGELOG.md | 5 +++++ src/main/java/com/nexmo/client/HttpWrapper.java | 15 +++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3550e0a0..c8e6590d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [Development] + +### Changed +- User Agent String now includes the Java version in addition to the client version. + ## [3.7.0] - 2018-08-10 ### Added - Added `RedactClient` and the ability to interact with the Nexmo Redact API. diff --git a/src/main/java/com/nexmo/client/HttpWrapper.java b/src/main/java/com/nexmo/client/HttpWrapper.java index 08c4b7012..93ba085bb 100644 --- a/src/main/java/com/nexmo/client/HttpWrapper.java +++ b/src/main/java/com/nexmo/client/HttpWrapper.java @@ -36,6 +36,10 @@ * Internal class that holds available authentication methods and a shared HttpClient. */ public class HttpWrapper { + private static final String CLIENT_NAME = "nexmo-java"; + private static final String CLIENT_VERSION = "3.7.0"; + private static final String JAVA_VERSION = System.getProperty("java.version"); + private AuthCollection authCollection; private HttpClient httpClient = null; @@ -74,8 +78,10 @@ protected HttpClient createHttpClient() { PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); connectionManager.setDefaultMaxPerRoute(200); connectionManager.setMaxTotal(200); - connectionManager.setDefaultConnectionConfig( - ConnectionConfig.custom().setCharset(Charset.forName("UTF-8")).build()); + connectionManager.setDefaultConnectionConfig(ConnectionConfig + .custom() + .setCharset(Charset.forName("UTF-8")) + .build()); connectionManager.setDefaultSocketConfig(SocketConfig.custom().setTcpNoDelay(true).build()); // Need to work out a good value for the following: @@ -83,9 +89,10 @@ protected HttpClient createHttpClient() { RequestConfig requestConfig = RequestConfig.custom().build(); - return HttpClientBuilder.create() + return HttpClientBuilder + .create() .setConnectionManager(connectionManager) - .setUserAgent("nexmo-java/3.7.0") + .setUserAgent(String.format("%s/%s java/%s", CLIENT_NAME, CLIENT_VERSION, JAVA_VERSION)) .setDefaultRequestConfig(requestConfig) .build(); } From 53a725c55fe3d7525f2ccdc36d1a113c53582d2c Mon Sep 17 00:00:00 2001 From: Steve Crow Date: Wed, 19 Sep 2018 10:19:01 -0400 Subject: [PATCH 3/8] Add Data Objects for Various Events (#191) * Add class to assist with deserializing of incoming sms json payloads. * Add class to assist with deserializing of call event json payloads. * Add class to assist with deserializing of input event json payloads. * Add class to assist with deserializing of record event json payloads. --- CHANGELOG.md | 5 + .../nexmo/client/incoming/CallDirection.java | 45 +++++++ .../com/nexmo/client/incoming/CallEvent.java | 79 ++++++++++++ .../com/nexmo/client/incoming/CallStatus.java | 59 +++++++++ .../com/nexmo/client/incoming/InputEvent.java | 70 ++++++++++ .../nexmo/client/incoming/MessageEvent.java | 122 ++++++++++++++++++ .../nexmo/client/incoming/MessageType.java | 45 +++++++ .../nexmo/client/incoming/RecordEvent.java | 83 ++++++++++++ .../client/incoming/CallDirectionTest.java | 38 ++++++ .../nexmo/client/incoming/CallEventTest.java | 55 ++++++++ .../nexmo/client/incoming/CallStatusTest.java | 38 ++++++ .../nexmo/client/incoming/InputEventTest.java | 51 ++++++++ .../client/incoming/MessageEventTest.java | 63 +++++++++ .../client/incoming/MessageTypeTest.java | 38 ++++++ .../client/incoming/RecordEventTest.java | 62 +++++++++ 15 files changed, 853 insertions(+) create mode 100644 src/main/java/com/nexmo/client/incoming/CallDirection.java create mode 100644 src/main/java/com/nexmo/client/incoming/CallEvent.java create mode 100644 src/main/java/com/nexmo/client/incoming/CallStatus.java create mode 100644 src/main/java/com/nexmo/client/incoming/InputEvent.java create mode 100644 src/main/java/com/nexmo/client/incoming/MessageEvent.java create mode 100644 src/main/java/com/nexmo/client/incoming/MessageType.java create mode 100644 src/main/java/com/nexmo/client/incoming/RecordEvent.java create mode 100644 src/test/java/com/nexmo/client/incoming/CallDirectionTest.java create mode 100644 src/test/java/com/nexmo/client/incoming/CallEventTest.java create mode 100644 src/test/java/com/nexmo/client/incoming/CallStatusTest.java create mode 100644 src/test/java/com/nexmo/client/incoming/InputEventTest.java create mode 100644 src/test/java/com/nexmo/client/incoming/MessageEventTest.java create mode 100644 src/test/java/com/nexmo/client/incoming/MessageTypeTest.java create mode 100644 src/test/java/com/nexmo/client/incoming/RecordEventTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index c8e6590d8..26577f100 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Development] +### Added +- Added `com.nexmo.client.incoming.MessageEvent` to assist with the deserialization of the JSON payload used for incoming messages. +- Added `com.nexmo.client.incoming.CallEvent` to assist with the deserialization of the JSON payload used for call events. +- Added `com.nexmo.client.incoming.InputEvent` to assist with the deserialization of the JSON payload used for input events. +- Added `com.nexmo.client.incoming.RecordEvent` to assist with the deserialization of the JSON payload used for record events. ### Changed - User Agent String now includes the Java version in addition to the client version. diff --git a/src/main/java/com/nexmo/client/incoming/CallDirection.java b/src/main/java/com/nexmo/client/incoming/CallDirection.java new file mode 100644 index 000000000..d241b7758 --- /dev/null +++ b/src/main/java/com/nexmo/client/incoming/CallDirection.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.incoming; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import java.util.HashMap; +import java.util.Map; + +public enum CallDirection { + OUTBOUND, INBOUND, UNKNOWN; + + private static final Map CALL_DIRECTION_INDEX = new HashMap<>(); + + static { + for (CallDirection callDirection : CallDirection.values()) { + CALL_DIRECTION_INDEX.put(callDirection.name(), callDirection); + } + } + + @JsonCreator + public static CallDirection fromString(String name) { + CallDirection foundCallDirection = CALL_DIRECTION_INDEX.get(name.toUpperCase()); + return (foundCallDirection != null) ? foundCallDirection : UNKNOWN; + } +} diff --git a/src/main/java/com/nexmo/client/incoming/CallEvent.java b/src/main/java/com/nexmo/client/incoming/CallEvent.java new file mode 100644 index 000000000..ea3dc04e9 --- /dev/null +++ b/src/main/java/com/nexmo/client/incoming/CallEvent.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.incoming; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.nexmo.client.NexmoUnexpectedException; + +import java.io.IOException; +import java.util.Date; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CallEvent { + private String conversationUuid; + private CallDirection direction; + private String from; + private CallStatus status; + private Date timestamp; + private String to; + private String uuid; + + @JsonProperty("conversation_uuid") + public String getConversationUuid() { + return conversationUuid; + } + + public CallDirection getDirection() { + return direction; + } + + public String getFrom() { + return from; + } + + public CallStatus getStatus() { + return status; + } + + public Date getTimestamp() { + return timestamp; + } + + public String getTo() { + return to; + } + + public String getUuid() { + return uuid; + } + + public static CallEvent fromJson(String json) { + try { + ObjectMapper mapper = new ObjectMapper(); + return mapper.readValue(json, CallEvent.class); + } catch (IOException jpe) { + throw new NexmoUnexpectedException("Failed to produce CallEvent from json.", jpe); + } + } +} diff --git a/src/main/java/com/nexmo/client/incoming/CallStatus.java b/src/main/java/com/nexmo/client/incoming/CallStatus.java new file mode 100644 index 000000000..4d7059733 --- /dev/null +++ b/src/main/java/com/nexmo/client/incoming/CallStatus.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.incoming; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import java.util.HashMap; +import java.util.Map; + +public enum CallStatus { + STARTED, + RINGING, + ANSWERED, + COMPLETED, + MACHINE, + HUMAN, + INPUT, + BUSY, + CANCELLED, + FAILED, + RECORDING, + REJECTED, + TIMEOUT, + UNANSWERED, + UNKNOWN; + + private static final Map CALL_STATUS_INDEX = new HashMap<>(); + + static { + for (CallStatus callStatus : CallStatus.values()) { + CALL_STATUS_INDEX.put(callStatus.name(), callStatus); + } + } + + @JsonCreator + public static CallStatus fromString(String status) { + CallStatus foundCallStatus = CALL_STATUS_INDEX.get(status.toUpperCase()); + return (foundCallStatus != null) ? foundCallStatus : UNKNOWN; + } +} diff --git a/src/main/java/com/nexmo/client/incoming/InputEvent.java b/src/main/java/com/nexmo/client/incoming/InputEvent.java new file mode 100644 index 000000000..8142fb444 --- /dev/null +++ b/src/main/java/com/nexmo/client/incoming/InputEvent.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.incoming; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.nexmo.client.NexmoUnexpectedException; + +import java.io.IOException; +import java.util.Date; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class InputEvent { + private String uuid; + private String conversationUuid; + private boolean timedOut; + private String dtmf; + private Date timestamp; + + public String getUuid() { + return uuid; + } + + @JsonProperty("conversation_uuid") + public String getConversationUuid() { + return conversationUuid; + } + + @JsonProperty("timed_out") + public boolean isTimedOut() { + return timedOut; + } + + public String getDtmf() { + return dtmf; + } + + public Date getTimestamp() { + return timestamp; + } + + public static InputEvent fromJson(String json) { + try { + ObjectMapper mapper = new ObjectMapper(); + return mapper.readValue(json, InputEvent.class); + } catch (IOException jpe) { + throw new NexmoUnexpectedException("Failed to produce InputEvent from json.", jpe); + } + } +} diff --git a/src/main/java/com/nexmo/client/incoming/MessageEvent.java b/src/main/java/com/nexmo/client/incoming/MessageEvent.java new file mode 100644 index 000000000..8208912be --- /dev/null +++ b/src/main/java/com/nexmo/client/incoming/MessageEvent.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.incoming; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.nexmo.client.NexmoUnexpectedException; + +import java.io.IOException; +import java.util.Date; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class MessageEvent { + private String msisdn; + private String to; + private String messageId; + private String text; + private MessageType type; + private String keyword; + private Date messageTimestamp; + private String timestamp; + private String nonce; + private Boolean concat; + private int concatRef; + private int concatTotal; + private int concatPart; + private String data; + private String udh; + + public String getMsisdn() { + return msisdn; + } + + public String getTo() { + return to; + } + + public String getMessageId() { + return messageId; + } + + public String getText() { + return text; + } + + public MessageType getType() { + return type; + } + + public String getKeyword() { + return keyword; + } + + @JsonProperty("message-timestamp") + public Date getMessageTimestamp() { + return messageTimestamp; + } + + public String getTimestamp() { + return timestamp; + } + + public String getNonce() { + return nonce; + } + + public Boolean getConcat() { + return concat; + } + + @JsonProperty("concat-ref") + public int getConcatRef() { + return concatRef; + } + + @JsonProperty("concat-total") + public int getConcatTotal() { + return concatTotal; + } + + @JsonProperty("concat-part") + public int getConcatPart() { + return concatPart; + } + + public String getData() { + return data; + } + + public String getUdh() { + return udh; + } + + public static MessageEvent fromJson(String json) { + try { + ObjectMapper mapper = new ObjectMapper(); + return mapper.readValue(json, MessageEvent.class); + } catch (IOException jpe) { + throw new NexmoUnexpectedException("Failed to produce MessageEvent from json.", jpe); + } + } +} diff --git a/src/main/java/com/nexmo/client/incoming/MessageType.java b/src/main/java/com/nexmo/client/incoming/MessageType.java new file mode 100644 index 000000000..bf4ebd475 --- /dev/null +++ b/src/main/java/com/nexmo/client/incoming/MessageType.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.incoming; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import java.util.HashMap; +import java.util.Map; + +public enum MessageType { + TEXT, UNICODE, BINARY, UNKNOWN; + + private static final Map MESSAGE_TYPE_INDEX = new HashMap<>(); + + static { + for (MessageType messageType : MessageType.values()) { + MESSAGE_TYPE_INDEX.put(messageType.name(), messageType); + } + } + + @JsonCreator + public static MessageType fromString(String name) { + MessageType foundMessageType = MESSAGE_TYPE_INDEX.get(name.toUpperCase()); + return (foundMessageType != null) ? foundMessageType : UNKNOWN; + } +} diff --git a/src/main/java/com/nexmo/client/incoming/RecordEvent.java b/src/main/java/com/nexmo/client/incoming/RecordEvent.java new file mode 100644 index 000000000..dbfc8dae5 --- /dev/null +++ b/src/main/java/com/nexmo/client/incoming/RecordEvent.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.incoming; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.nexmo.client.NexmoUnexpectedException; + +import java.io.IOException; +import java.util.Date; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class RecordEvent { + private Date startTime; + private String url; + private int size; + private String uuid; + private Date endTime; + private String conversationUuid; + private Date timestamp; + + @JsonProperty("start_time") + public Date getStartTime() { + return startTime; + } + + @JsonProperty("recording_url") + public String getUrl() { + return url; + } + + public int getSize() { + return size; + } + + @JsonProperty("recording_uuid") + public String getUuid() { + return uuid; + } + + @JsonProperty("end_time") + public Date getEndTime() { + return endTime; + } + + @JsonProperty("conversation_uuid") + public String getConversationUuid() { + return conversationUuid; + } + + public Date getTimestamp() { + return timestamp; + } + + public static RecordEvent fromJson(String json) { + try { + ObjectMapper mapper = new ObjectMapper(); + return mapper.readValue(json, RecordEvent.class); + } catch (IOException jpe) { + throw new NexmoUnexpectedException("Failed to produce RecordEvent from json.", jpe); + } + } +} diff --git a/src/test/java/com/nexmo/client/incoming/CallDirectionTest.java b/src/test/java/com/nexmo/client/incoming/CallDirectionTest.java new file mode 100644 index 000000000..ab2a5490c --- /dev/null +++ b/src/test/java/com/nexmo/client/incoming/CallDirectionTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.incoming; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class CallDirectionTest { + @Test + public void testCallDirectionFromString() { + assertEquals(CallDirection.OUTBOUND, CallDirection.fromString("outbound")); + } + + @Test + public void testDeserializeUnknownEnumsFallbackToUnknown() { + assertEquals(CallDirection.UNKNOWN, CallDirection.fromString("test")); + } +} diff --git a/src/test/java/com/nexmo/client/incoming/CallEventTest.java b/src/test/java/com/nexmo/client/incoming/CallEventTest.java new file mode 100644 index 000000000..a495d0223 --- /dev/null +++ b/src/test/java/com/nexmo/client/incoming/CallEventTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.incoming; + +import org.junit.Test; + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +import static org.junit.Assert.assertEquals; + +public class CallEventTest { + @Test + public void testDeserializeCallEvent() { + String json = "{\n" + " \"conversation_uuid\": \"CON-4bf66420-d6cb-46e0-9ba9-f7eede9a7301\",\n" + + " \"direction\": \"inbound\",\n" + " \"from\": \"447700900000\",\n" + + " \"status\": \"started\",\n" + " \"timestamp\": \"2018-08-14T11:07:01.284Z\",\n" + + " \"to\": \"447700900001\",\n" + " \"uuid\": \"688fd94bd0e1f59c36a4cbd36312fc28\"\n" + "}"; + + CallEvent callEvent = CallEvent.fromJson(json); + assertEquals("CON-4bf66420-d6cb-46e0-9ba9-f7eede9a7301", callEvent.getConversationUuid()); + assertEquals(CallDirection.INBOUND, callEvent.getDirection()); + assertEquals("447700900000", callEvent.getFrom()); + assertEquals(CallStatus.STARTED, callEvent.getStatus()); + assertEquals("447700900001", callEvent.getTo()); + assertEquals("688fd94bd0e1f59c36a4cbd36312fc28", callEvent.getUuid()); + + Calendar calendar = new GregorianCalendar(2018, Calendar.AUGUST, 14, 11, 7, 1); + calendar.set(Calendar.MILLISECOND, 284); + calendar.setTimeZone(TimeZone.getTimeZone("UTC")); + + assertEquals(calendar.getTime(), callEvent.getTimestamp()); + + } +} diff --git a/src/test/java/com/nexmo/client/incoming/CallStatusTest.java b/src/test/java/com/nexmo/client/incoming/CallStatusTest.java new file mode 100644 index 000000000..94d9eb28d --- /dev/null +++ b/src/test/java/com/nexmo/client/incoming/CallStatusTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.incoming; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class CallStatusTest { + @Test + public void testCallDirectionFromString() { + assertEquals(CallStatus.FAILED, CallStatus.fromString("failed")); + } + + @Test + public void testDeserializeUnknownEnumsFallbackToUnknown() { + assertEquals(CallStatus.UNKNOWN, CallStatus.fromString("test")); + } +} diff --git a/src/test/java/com/nexmo/client/incoming/InputEventTest.java b/src/test/java/com/nexmo/client/incoming/InputEventTest.java new file mode 100644 index 000000000..e54b34ea1 --- /dev/null +++ b/src/test/java/com/nexmo/client/incoming/InputEventTest.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.incoming; + +import org.junit.Test; + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class InputEventTest { + @Test + public void testDeserializeInputEvent() { + String json = "{\n" + " \"uuid\": \"aaaaaaaa-bbbb-cccc-dddd-0123456789ab\",\n" + + " \"conversation_uuid\": \"bbbbbbbb-cccc-dddd-eeee-0123456789ab\",\n" + " \"timed_out\": true,\n" + + " \"dtmf\": \"1234\",\n" + " \"timestamp\": \"2020-01-01T14:00:00.000Z\"\n" + "}"; + + InputEvent inputEvent = InputEvent.fromJson(json); + assertEquals("aaaaaaaa-bbbb-cccc-dddd-0123456789ab", inputEvent.getUuid()); + assertEquals("bbbbbbbb-cccc-dddd-eeee-0123456789ab", inputEvent.getConversationUuid()); + assertTrue(inputEvent.isTimedOut()); + assertEquals("1234", inputEvent.getDtmf()); + + Calendar calendar = new GregorianCalendar(2020, Calendar.JANUARY, 1, 14, 0, 0); + calendar.setTimeZone(TimeZone.getTimeZone("UTC")); + + assertEquals(calendar.getTime(), inputEvent.getTimestamp()); + } +} diff --git a/src/test/java/com/nexmo/client/incoming/MessageEventTest.java b/src/test/java/com/nexmo/client/incoming/MessageEventTest.java new file mode 100644 index 000000000..6cae0b998 --- /dev/null +++ b/src/test/java/com/nexmo/client/incoming/MessageEventTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.incoming; + +import org.junit.Test; + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +import static org.junit.Assert.assertEquals; + +public class MessageEventTest { + @Test + public void testDeserializeIncomingMessage() { + String json = "{\n" + " \"msisdn\": \"447700900001\",\n" + " \"to\": \"447700900000\",\n" + + " \"messageId\": \"0A0000000123ABCD1\",\n" + " \"text\": \"Hello world\",\n" + + " \"type\": \"text\",\n" + " \"keyword\": \"Hello\",\n" + + " \"message-timestamp\": \"2020-01-01T12:00:00.000+00:00\",\n" + " \"timestamp\": \"1578787200\",\n" + + " \"nonce\": \"aaaaaaaa-bbbb-cccc-dddd-0123456789ab\",\n" + " \"concat\": \"true\",\n" + + " \"concat-ref\": \"1\",\n" + " \"concat-total\": \"3\",\n" + " \"concat-part\": \"2\",\n" + + " \"data\": \"abc123\",\n" + " \"udh\": \"abc123\"\n" + "}"; + + MessageEvent messageEvent = MessageEvent.fromJson(json); + assertEquals("447700900001", messageEvent.getMsisdn()); + assertEquals("447700900000", messageEvent.getTo()); + assertEquals("0A0000000123ABCD1", messageEvent.getMessageId()); + assertEquals("Hello world", messageEvent.getText()); + assertEquals("Hello", messageEvent.getKeyword()); + assertEquals("1578787200", messageEvent.getTimestamp()); + assertEquals("aaaaaaaa-bbbb-cccc-dddd-0123456789ab", messageEvent.getNonce()); + assertEquals(true, messageEvent.getConcat()); + assertEquals(1, messageEvent.getConcatRef()); + assertEquals(3, messageEvent.getConcatTotal()); + assertEquals(2, messageEvent.getConcatPart()); + assertEquals("abc123", messageEvent.getData()); + assertEquals("abc123", messageEvent.getUdh()); + + Calendar calendar = new GregorianCalendar(2020, Calendar.JANUARY, 1, 12, 0, 0); + calendar.setTimeZone(TimeZone.getTimeZone("UTC")); + + assertEquals(calendar.getTime(), messageEvent.getMessageTimestamp()); + } +} diff --git a/src/test/java/com/nexmo/client/incoming/MessageTypeTest.java b/src/test/java/com/nexmo/client/incoming/MessageTypeTest.java new file mode 100644 index 000000000..09cfa9e2f --- /dev/null +++ b/src/test/java/com/nexmo/client/incoming/MessageTypeTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.incoming; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class MessageTypeTest { + @Test + public void testMessageTypeFromString() { + assertEquals(MessageType.TEXT, MessageType.fromString("text")); + } + + @Test + public void testDeserializeUnknownEnumsFallbackToUnknown() { + assertEquals(MessageType.UNKNOWN, MessageType.fromString("test")); + } +} diff --git a/src/test/java/com/nexmo/client/incoming/RecordEventTest.java b/src/test/java/com/nexmo/client/incoming/RecordEventTest.java new file mode 100644 index 000000000..8194ca091 --- /dev/null +++ b/src/test/java/com/nexmo/client/incoming/RecordEventTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.incoming; + +import org.junit.Test; + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +import static org.junit.Assert.assertEquals; + +public class RecordEventTest { + @Test + public void testDeserializeRecordEvent() { + String json = "{\n" + " \"start_time\": \"2020-01-01T12:00:00Z\",\n" + + " \"recording_url\": \"https://api.nexmo.com/media/download?id=aaaaaaaa-bbbb-cccc-dddd-0123456789ab\",\n" + + " \"size\": 12345,\n" + " \"recording_uuid\": \"aaaaaaaa-bbbb-cccc-dddd-0123456789ab\",\n" + + " \"end_time\": \"2020-01-01T12:01:00Z\",\n" + + " \"conversation_uuid\": \"bbbbbbbb-cccc-dddd-eeee-0123456789ab\",\n" + + " \"timestamp\": \"2020-01-01T14:00:00.000Z\"\n" + "}"; + + RecordEvent recordEvent = RecordEvent.fromJson(json); + assertEquals("https://api.nexmo.com/media/download?id=aaaaaaaa-bbbb-cccc-dddd-0123456789ab", + recordEvent.getUrl() + ); + assertEquals(12345, recordEvent.getSize()); + assertEquals("aaaaaaaa-bbbb-cccc-dddd-0123456789ab", recordEvent.getUuid()); + assertEquals("bbbbbbbb-cccc-dddd-eeee-0123456789ab", recordEvent.getConversationUuid()); + + Calendar startTime = new GregorianCalendar(2020, Calendar.JANUARY, 1, 12, 0, 0); + startTime.setTimeZone(TimeZone.getTimeZone("UTC")); + assertEquals(startTime.getTime(), recordEvent.getStartTime()); + + Calendar endTime = new GregorianCalendar(2020, Calendar.JANUARY, 1, 12, 1, 0); + endTime.setTimeZone(TimeZone.getTimeZone("UTC")); + assertEquals(endTime.getTime(), recordEvent.getEndTime()); + + Calendar timestamp = new GregorianCalendar(2020, Calendar.JANUARY, 1, 14, 0, 0); + timestamp.setTimeZone(TimeZone.getTimeZone("UTC")); + assertEquals(timestamp.getTime(), recordEvent.getTimestamp()); + } +} From 036bdcec6841ea5e3e09b24047c552071e822497 Mon Sep 17 00:00:00 2001 From: Steve Crow Date: Wed, 19 Sep 2018 10:23:59 -0400 Subject: [PATCH 4/8] Jackson will use an alternative method in order to serealize streamUrl as an array. (#190) --- CHANGELOG.md | 3 +++ .../com/nexmo/client/voice/ncco/StreamNcco.java | 16 ++++++++++++---- .../nexmo/client/voice/ncco/StreamNccoTest.java | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26577f100..bd17ec34e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed - User Agent String now includes the Java version in addition to the client version. +### Fixed +- Updated `StreamNcco`'s `streamUrl` to serialize into an array for use in the Voice API. + ## [3.7.0] - 2018-08-10 ### Added - Added `RedactClient` and the ability to interact with the Nexmo Redact API. diff --git a/src/main/java/com/nexmo/client/voice/ncco/StreamNcco.java b/src/main/java/com/nexmo/client/voice/ncco/StreamNcco.java index d28d2b661..72003fd27 100644 --- a/src/main/java/com/nexmo/client/voice/ncco/StreamNcco.java +++ b/src/main/java/com/nexmo/client/voice/ncco/StreamNcco.java @@ -35,16 +35,24 @@ public class StreamNcco implements Ncco { private Boolean bargeIn = null; private Integer loop = null; - public StreamNcco(@JsonProperty("streamUrl") String streamUrl) { - this.streamUrl = streamUrl; + public StreamNcco(@JsonProperty("streamUrl") String... streamUrl) { + this.streamUrl = streamUrl[0]; } public String getStreamUrl() { return streamUrl; } - public void setStreamUrl(String streamUrl) { - this.streamUrl = streamUrl; + @JsonProperty("streamUrl") + public String[] getStreamUrlAsArray() { + // TODO: Rework in 4.0. + // This property is expected to be serialized as an array, however we want to also insure it remains null + // if null. + return this.streamUrl != null ? new String[]{this.streamUrl} : null; + } + + public void setStreamUrl(String... streamUrl) { + this.streamUrl = streamUrl[0]; } public Float getLevel() { diff --git a/src/test/java/com/nexmo/client/voice/ncco/StreamNccoTest.java b/src/test/java/com/nexmo/client/voice/ncco/StreamNccoTest.java index a59ee7fb9..1297536bc 100644 --- a/src/test/java/com/nexmo/client/voice/ncco/StreamNccoTest.java +++ b/src/test/java/com/nexmo/client/voice/ncco/StreamNccoTest.java @@ -30,7 +30,7 @@ public class StreamNccoTest { @Test public void testToJson() throws Exception { assertEquals( - "{\"streamUrl\":\"https://api.example.com/stream\",\"action\":\"stream\"}", + "{\"streamUrl\":[\"https://api.example.com/stream\"],\"action\":\"stream\"}", new StreamNcco("https://api.example.com/stream").toJson()); } From 7997deb9bceee8f4802cfff053df82e25383d121 Mon Sep 17 00:00:00 2001 From: Steve Crow Date: Wed, 19 Sep 2018 10:27:35 -0400 Subject: [PATCH 5/8] Add fallback values to enums (#187) * Update enums used during deserialization of advanced insight request to fallback to an unknown value instead of throwing an IllegalArgumentException. * Update enums used during deserialization of call status request to fallback to an unknown value instead of throwing an IllegalArgumentException. * ModifyCallAction will return UNKNOWN instead of throwing an IllegalArgumentException when deserializing unknown values. * VoiceName will return UNKNOWN instead of throwing an IllegalArgumentException when deserializing unknown values. * MachineDetection will return UNKNOWN instead of throwing an IllegalArgumentException when deserializing unknown values. * RecordingFormat will return UNKNOWN instead of throwing an IllegalArgumentException when deserializing unknown values. * Update CHANGELOG. * The index map should be in SCREAMING_SNAKE_CASE since it's technically a constant. --- CHANGELOG.md | 10 ++++ .../nexmo/client/insight/RoamingDetails.java | 18 +++++-- .../advanced/AdvancedInsightResponse.java | 52 +++++++++++++------ .../com/nexmo/client/voice/CallDirection.java | 17 +++++- .../com/nexmo/client/voice/CallStatus.java | 17 +++++- .../nexmo/client/voice/MachineDetection.java | 17 ++++-- .../nexmo/client/voice/ModifyCallAction.java | 21 +++++--- .../com/nexmo/client/voice/VoiceName.java | 17 +++++- .../client/voice/ncco/RecordingFormat.java | 17 ++++-- .../advanced/AdvancedInsightResponseTest.java | 20 +++++++ .../client/voice/MachineDetectionTest.java | 38 ++++++++++++++ .../client/voice/ModifyCallActionTest.java | 34 ++++++++++++ .../com/nexmo/client/voice/VoiceNameTest.java | 38 ++++++++++++++ .../client/voice/endpoints/CallInfoTest.java | 33 ++++++++++++ .../voice/ncco/RecordingFormatTest.java | 3 +- 15 files changed, 311 insertions(+), 41 deletions(-) create mode 100644 src/test/java/com/nexmo/client/voice/MachineDetectionTest.java create mode 100644 src/test/java/com/nexmo/client/voice/ModifyCallActionTest.java create mode 100644 src/test/java/com/nexmo/client/voice/VoiceNameTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index bd17ec34e..74e2ea0ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed - User Agent String now includes the Java version in addition to the client version. +- `enum` classes that are used to deserialize JSON have been updated to return an `UNKNOWN` value instead of throwing an `IllegalArgumentException` when the value cannot be deserialized. These `enum`s are: + - `RecordingFormat` + - `MachineDetection` + - `ModifyCallAction` + - `CallDirection` + - `CallStatus` + - `RoamingDetails.RoamingStatus` + - `AdvancedInsightResponse.PortedStatus` + - `AdvancedInsightResponse.Validity` + - `AdvancedInsightResponse.Reachability` ### Fixed - Updated `StreamNcco`'s `streamUrl` to serialize into an array for use in the Voice API. diff --git a/src/main/java/com/nexmo/client/insight/RoamingDetails.java b/src/main/java/com/nexmo/client/insight/RoamingDetails.java index df01db58d..cdbea5fa1 100644 --- a/src/main/java/com/nexmo/client/insight/RoamingDetails.java +++ b/src/main/java/com/nexmo/client/insight/RoamingDetails.java @@ -24,15 +24,25 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.HashMap; +import java.util.Map; + public class RoamingDetails { public enum RoamingStatus { - UNKNOWN, - ROAMING, - NOT_ROAMING; + UNKNOWN, ROAMING, NOT_ROAMING; + + private static final Map ROAMING_STATUS_INDEX = new HashMap<>(); + + static { + for (RoamingStatus roamingStatus : RoamingStatus.values()) { + ROAMING_STATUS_INDEX.put(roamingStatus.name(), roamingStatus); + } + } @JsonCreator public static RoamingStatus fromString(String name) { - return RoamingStatus.valueOf(name.toUpperCase()); + RoamingStatus foundRoamingStatus = ROAMING_STATUS_INDEX.get(name.toUpperCase()); + return (foundRoamingStatus != null) ? foundRoamingStatus : UNKNOWN; } } diff --git a/src/main/java/com/nexmo/client/insight/advanced/AdvancedInsightResponse.java b/src/main/java/com/nexmo/client/insight/advanced/AdvancedInsightResponse.java index f37993298..56503bcbf 100644 --- a/src/main/java/com/nexmo/client/insight/advanced/AdvancedInsightResponse.java +++ b/src/main/java/com/nexmo/client/insight/advanced/AdvancedInsightResponse.java @@ -31,6 +31,8 @@ import com.nexmo.client.insight.standard.StandardInsightResponse; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; @JsonIgnoreProperties(ignoreUnknown = true) public class AdvancedInsightResponse extends StandardInsightResponse { @@ -104,41 +106,57 @@ public CallerType getCallerType() { } public enum PortedStatus { - UNKNOWN, - PORTED, - NOT_PORTED, - ASSUMED_NOT_PORTED, - ASSUMED_PORTED; + UNKNOWN, PORTED, NOT_PORTED, ASSUMED_NOT_PORTED, ASSUMED_PORTED; + + private static final Map PORTED_STATUS_INDEX = new HashMap<>(); + + static { + for (PortedStatus portedStatus : PortedStatus.values()) { + PORTED_STATUS_INDEX.put(portedStatus.name(), portedStatus); + } + } @JsonCreator public static PortedStatus fromString(String name) { - return PortedStatus.valueOf(name.toUpperCase()); + PortedStatus foundPortedStatus = PORTED_STATUS_INDEX.get(name.toUpperCase()); + return (foundPortedStatus != null) ? foundPortedStatus : UNKNOWN; } } public enum Validity { - UNKNOWN, - VALID, - NOT_VALID; + UNKNOWN, VALID, NOT_VALID; + + private static final Map VALIDITY_INDEX = new HashMap<>(); + + static { + for (Validity validity : Validity.values()) { + VALIDITY_INDEX.put(validity.name(), validity); + } + } @JsonCreator public static Validity fromString(String name) { - return Validity.valueOf(name.toUpperCase()); + Validity foundValidity = VALIDITY_INDEX.get(name.toUpperCase()); + return (foundValidity != null) ? foundValidity : Validity.UNKNOWN; } } public enum Reachability { - UNKNOWN, - REACHABLE, - UNDELIVERABLE, - ABSENT, - BAD_NUMBER, - BLACKLISTED; + UNKNOWN, REACHABLE, UNDELIVERABLE, ABSENT, BAD_NUMBER, BLACKLISTED; + + private static final Map REACHABILITY_INDEX = new HashMap<>(); + + static { + for (Reachability reachability : Reachability.values()) { + REACHABILITY_INDEX.put(reachability.name(), reachability); + } + } @JsonCreator public static Reachability fromString(String name) { - return Reachability.valueOf(name.toUpperCase()); + Reachability foundReachability = REACHABILITY_INDEX.get(name.toUpperCase()); + return (foundReachability != null) ? foundReachability : UNKNOWN; } } } diff --git a/src/main/java/com/nexmo/client/voice/CallDirection.java b/src/main/java/com/nexmo/client/voice/CallDirection.java index 5b4ed0bc7..87aee5d62 100644 --- a/src/main/java/com/nexmo/client/voice/CallDirection.java +++ b/src/main/java/com/nexmo/client/voice/CallDirection.java @@ -24,9 +24,21 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; +import java.util.HashMap; +import java.util.Map; + public enum CallDirection { OUTBOUND, - INBOUND; + INBOUND, + UNKNOWN; + + private static final Map CALL_DIRECTION_INDEX = new HashMap<>(); + + static { + for (CallDirection callDirection : CallDirection.values()) { + CALL_DIRECTION_INDEX.put(callDirection.name(), callDirection); + } + } @JsonValue @Override @@ -36,6 +48,7 @@ public String toString() { @JsonCreator public static CallDirection fromString(String name) { - return CallDirection.valueOf(name.toUpperCase()); + CallDirection foundCallDirection = CALL_DIRECTION_INDEX.get(name.toUpperCase()); + return (foundCallDirection != null) ? foundCallDirection : UNKNOWN; } } \ No newline at end of file diff --git a/src/main/java/com/nexmo/client/voice/CallStatus.java b/src/main/java/com/nexmo/client/voice/CallStatus.java index 26e0fd213..b41208bea 100644 --- a/src/main/java/com/nexmo/client/voice/CallStatus.java +++ b/src/main/java/com/nexmo/client/voice/CallStatus.java @@ -24,6 +24,9 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; +import java.util.HashMap; +import java.util.Map; + public enum CallStatus { STARTED, RINGING, @@ -34,7 +37,16 @@ public enum CallStatus { FAILED, REJECTED, BUSY, - CANCELLED; + CANCELLED, + UNKNOWN; + + private static final Map CALL_STATUS_INDEX = new HashMap<>(); + + static { + for (CallStatus callStatus : CallStatus.values()) { + CALL_STATUS_INDEX.put(callStatus.name(), callStatus); + } + } @JsonValue @Override @@ -44,6 +56,7 @@ public String toString() { @JsonCreator public static CallStatus fromString(String name) { - return CallStatus.valueOf(name.toUpperCase()); + CallStatus foundCallStatus = CALL_STATUS_INDEX.get(name.toUpperCase()); + return (foundCallStatus != null) ? foundCallStatus : UNKNOWN; } } diff --git a/src/main/java/com/nexmo/client/voice/MachineDetection.java b/src/main/java/com/nexmo/client/voice/MachineDetection.java index d9c29c73f..038d7d6c0 100644 --- a/src/main/java/com/nexmo/client/voice/MachineDetection.java +++ b/src/main/java/com/nexmo/client/voice/MachineDetection.java @@ -24,9 +24,19 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; +import java.util.HashMap; +import java.util.Map; + public enum MachineDetection { - CONTINUE, - HANGUP; + CONTINUE, HANGUP, UNKNOWN; + + private static final Map MACHINE_DETECTION_INDEX = new HashMap<>(); + + static { + for (MachineDetection machineDetection : MachineDetection.values()) { + MACHINE_DETECTION_INDEX.put(machineDetection.name(), machineDetection); + } + } @JsonValue @Override @@ -36,6 +46,7 @@ public String toString() { @JsonCreator public static MachineDetection fromString(String name) { - return MachineDetection.valueOf(name.toUpperCase()); + MachineDetection foundMachineDetection = MACHINE_DETECTION_INDEX.get(name.toUpperCase()); + return (foundMachineDetection != null) ? foundMachineDetection : UNKNOWN; } } diff --git a/src/main/java/com/nexmo/client/voice/ModifyCallAction.java b/src/main/java/com/nexmo/client/voice/ModifyCallAction.java index a99164826..945248748 100644 --- a/src/main/java/com/nexmo/client/voice/ModifyCallAction.java +++ b/src/main/java/com/nexmo/client/voice/ModifyCallAction.java @@ -24,13 +24,19 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; +import java.util.HashMap; +import java.util.Map; + public enum ModifyCallAction { - HANGUP, - MUTE, - UNMUTE, - EARMUFF, - UNEARMUFF, - TRANSFER; + HANGUP, MUTE, UNMUTE, EARMUFF, UNEARMUFF, TRANSFER, UNKNOWN; + + private static final Map MODIFY_CALL_ACTION_INDEX = new HashMap<>(); + + static { + for (ModifyCallAction modifyCallAction : ModifyCallAction.values()) { + MODIFY_CALL_ACTION_INDEX.put(modifyCallAction.name(), modifyCallAction); + } + } @JsonValue @Override @@ -40,6 +46,7 @@ public String toString() { @JsonCreator public static ModifyCallAction fromString(String name) { - return ModifyCallAction.valueOf(name.toUpperCase()); + ModifyCallAction foundModifyCallAction = MODIFY_CALL_ACTION_INDEX.get(name.toUpperCase()); + return (foundModifyCallAction != null) ? foundModifyCallAction : UNKNOWN; } } diff --git a/src/main/java/com/nexmo/client/voice/VoiceName.java b/src/main/java/com/nexmo/client/voice/VoiceName.java index 3603af506..07b3d1759 100644 --- a/src/main/java/com/nexmo/client/voice/VoiceName.java +++ b/src/main/java/com/nexmo/client/voice/VoiceName.java @@ -25,6 +25,9 @@ import com.fasterxml.jackson.annotation.JsonValue; import org.apache.commons.lang3.StringUtils; +import java.util.HashMap; +import java.util.Map; + /** * Voice used to deliver text to a {@link Call} in a {@link TalkRequest}. */ @@ -78,7 +81,16 @@ public enum VoiceName { MAXIM, TATYANA, ASTRID, - FILIZ; + FILIZ, + UNKNOWN; + + private static final Map voiceNameIndex = new HashMap<>(); + + static { + for (VoiceName voiceName : VoiceName.values()) { + voiceNameIndex.put(voiceName.name(), voiceName); + } + } @JsonValue @Override @@ -89,7 +101,8 @@ public String toString() { @JsonCreator public static VoiceName fromString(String name) { - return VoiceName.valueOf(name.toUpperCase()); + VoiceName foundVoiceName = voiceNameIndex.get(name.toUpperCase()); + return (foundVoiceName != null) ? foundVoiceName : UNKNOWN; } } diff --git a/src/main/java/com/nexmo/client/voice/ncco/RecordingFormat.java b/src/main/java/com/nexmo/client/voice/ncco/RecordingFormat.java index 0cf3c94a6..d21a8ebe0 100644 --- a/src/main/java/com/nexmo/client/voice/ncco/RecordingFormat.java +++ b/src/main/java/com/nexmo/client/voice/ncco/RecordingFormat.java @@ -24,9 +24,19 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; +import java.util.HashMap; +import java.util.Map; + public enum RecordingFormat { - MP3, - WAV; + MP3, WAV, UNKNOWN; + + private static final Map RECORDING_FORMAT_INDEX = new HashMap<>(); + + static { + for (RecordingFormat recordingFormat : RecordingFormat.values()) { + RECORDING_FORMAT_INDEX.put(recordingFormat.name(), recordingFormat); + } + } @JsonValue @Override @@ -36,6 +46,7 @@ public String toString() { @JsonCreator public static RecordingFormat fromString(String name) { - return RecordingFormat.valueOf(name.toUpperCase()); + RecordingFormat foundRecordingFormat = RECORDING_FORMAT_INDEX.get(name.toUpperCase()); + return (foundRecordingFormat != null) ? foundRecordingFormat : UNKNOWN; } } \ No newline at end of file diff --git a/src/test/java/com/nexmo/client/insight/advanced/AdvancedInsightResponseTest.java b/src/test/java/com/nexmo/client/insight/advanced/AdvancedInsightResponseTest.java index 2dca59b9a..8e4d875ff 100644 --- a/src/test/java/com/nexmo/client/insight/advanced/AdvancedInsightResponseTest.java +++ b/src/test/java/com/nexmo/client/insight/advanced/AdvancedInsightResponseTest.java @@ -107,6 +107,26 @@ public void testFromJson() throws Exception { assertEquals(CallerType.UNKNOWN, response.getCallerType()); } + @Test + public void testDeserializeUnknownEnumsFallbackToUnknown() throws Exception { + AdvancedInsightResponse response = AdvancedInsightResponse.fromJson("{\n" + + " \"valid_number\": \"failed_validity\",\n" + + " \"reachable\": \"failed_reachibility\",\n" + + " \"ported\": \"failure_ported_status\",\n" + + " \"roaming\": {\n" + + " \"status\": \"failure_roaming_status\",\n" + + " \"roaming_country_code\": \"GB\",\n" + + " \"roaming_network_code\": \"gong\",\n" + + " \"roaming_network_name\": \"Gong Telecommunications\"\n" + + " }\n" + + "}"); + + assertEquals(AdvancedInsightResponse.Validity.UNKNOWN, response.getValidNumber()); + assertEquals(AdvancedInsightResponse.Reachability.UNKNOWN, response.getReachability()); + assertEquals(AdvancedInsightResponse.PortedStatus.UNKNOWN, response.getPorted()); + assertEquals(RoamingDetails.RoamingStatus.UNKNOWN, response.getRoaming().getStatus()); + } + @Test public void testRoamingDeserialization() throws Exception { AdvancedInsightResponse response = AdvancedInsightResponse.fromJson("{\n" + diff --git a/src/test/java/com/nexmo/client/voice/MachineDetectionTest.java b/src/test/java/com/nexmo/client/voice/MachineDetectionTest.java new file mode 100644 index 000000000..353f89630 --- /dev/null +++ b/src/test/java/com/nexmo/client/voice/MachineDetectionTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.voice; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class MachineDetectionTest { + @Test + public void testMachineDetectionFromString() { + assertEquals(MachineDetection.HANGUP, MachineDetection.fromString("hangup")); + } + + @Test + public void testDeserializeUnknownEnumsFallbackToUnknown() { + assertEquals(MachineDetection.UNKNOWN, MachineDetection.fromString("test unknown machine detection")); + } +} diff --git a/src/test/java/com/nexmo/client/voice/ModifyCallActionTest.java b/src/test/java/com/nexmo/client/voice/ModifyCallActionTest.java new file mode 100644 index 000000000..cda4e0fa5 --- /dev/null +++ b/src/test/java/com/nexmo/client/voice/ModifyCallActionTest.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.voice; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ModifyCallActionTest { + @Test + public void testDeserializeUnknownEnumsFallbackToUnknown() { + assertEquals(ModifyCallAction.UNKNOWN, ModifyCallAction.fromString("test unknwon action")); + } + +} diff --git a/src/test/java/com/nexmo/client/voice/VoiceNameTest.java b/src/test/java/com/nexmo/client/voice/VoiceNameTest.java new file mode 100644 index 000000000..62c74ef9a --- /dev/null +++ b/src/test/java/com/nexmo/client/voice/VoiceNameTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.voice; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class VoiceNameTest { + @Test + public void testGetVoiceNameFromString() { + assertEquals(VoiceName.CARLA, VoiceName.fromString("Carla")); + } + + @Test + public void testDeserializeUnknownEnumsFallbackToUnknown() { + assertEquals(VoiceName.UNKNOWN, VoiceName.fromString("Test Unknown Voice Name")); + } +} diff --git a/src/test/java/com/nexmo/client/voice/endpoints/CallInfoTest.java b/src/test/java/com/nexmo/client/voice/endpoints/CallInfoTest.java index bf3c21617..d24a8f736 100644 --- a/src/test/java/com/nexmo/client/voice/endpoints/CallInfoTest.java +++ b/src/test/java/com/nexmo/client/voice/endpoints/CallInfoTest.java @@ -115,6 +115,39 @@ public void testJson() throws Exception { assertEquals(new PhoneEndpoint("447700900105"), record.getFrom()); } + @Test + public void testDeserializeUnknownEnumsFallbackToUnknown() throws Exception { + String json = "{\n" + + " \"uuid\": \"93137ee3-580e-45f7-a61a-e0b5716000ef\",\n" + + " \"status\": \"test-unknown-call-status\",\n" + + " \"direction\": \"test-unknown-direction\",\n" + + " \"rate\": \"0.02400000\",\n" + + " \"price\": \"0.00280000\",\n" + + " \"duration\": \"7\",\n" + + " \"network\": \"23410\",\n" + + " \"conversation_uuid\": \"aa17bd11-c895-4225-840d-30dc38c31e50\",\n" + + " \"start_time\": \"2017-01-13T13:55:02.000Z\",\n" + + " \"end_time\": \"2017-01-13T13:55:09.000Z\",\n" + + " \"to\": {\n" + + " \"type\": \"phone\",\n" + + " \"number\": \"447700900104\"\n" + + " },\n" + + " \"from\": {\n" + + " \"type\": \"phone\",\n" + + " \"number\": \"447700900105\"\n" + + " },\n" + + " \"_links\": {\n" + + " \"self\": {\n" + + " \"href\": \"/v1/calls/93137ee3-580e-45f7-a61a-e0b5716000ef\"\n" + + " }\n" + + " }\n" + + "}\n"; + CallInfo record = new ObjectMapper().readValue(json, CallInfo.class); + + assertEquals(CallStatus.UNKNOWN, record.getStatus()); + assertEquals(CallDirection.UNKNOWN, record.getDirection()); + } + @Test public void testStatusStarted() throws Exception { diff --git a/src/test/java/com/nexmo/client/voice/ncco/RecordingFormatTest.java b/src/test/java/com/nexmo/client/voice/ncco/RecordingFormatTest.java index b06994d18..108f96f3c 100644 --- a/src/test/java/com/nexmo/client/voice/ncco/RecordingFormatTest.java +++ b/src/test/java/com/nexmo/client/voice/ncco/RecordingFormatTest.java @@ -23,13 +23,14 @@ import org.junit.Test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; public class RecordingFormatTest { @Test public void testFromString() throws Exception { assertEquals(RecordingFormat.MP3, RecordingFormat.fromString("mp3")); assertEquals(RecordingFormat.WAV, RecordingFormat.fromString("wav")); + assertEquals(RecordingFormat.UNKNOWN, RecordingFormat.fromString("test unknown")); } @Test From 10a3bff7df124f835d3405cc6b762108f0490579 Mon Sep 17 00:00:00 2001 From: Steve Crow Date: Wed, 19 Sep 2018 10:33:41 -0400 Subject: [PATCH 6/8] Implement Secret Management (#189) * Fix incorrect document block. * Add dependency on jackson-dataformat-hal to assist with deserializing HATEOAS responses. * Add methods for creating secrets. * Add method to list secrets. * Add method to revoke secrets. * Add method for retrieving secrets. * Add response object for listing secrets. * Add tests for secret management methods. * Add secret management endpoint and methods to account client. * Update CHANGELOG for secret management. * Add information to README on how to use secret management. * Rename account id to api key. --- CHANGELOG.md | 5 + README.md | 42 +++ build.gradle | 1 + .../nexmo/client/account/AccountClient.java | 85 +++++- .../client/account/CreateSecretMethod.java | 85 ++++++ .../client/account/CreateSecretRequest.java | 55 ++++ .../nexmo/client/account/GetSecretMethod.java | 81 ++++++ .../client/account/ListSecretsMethod.java | 77 ++++++ .../client/account/ListSecretsResponse.java | 57 +++++ .../client/account/RevokeSecretMethod.java | 80 ++++++ .../account/SecretManagementEndpoint.java | 58 +++++ .../nexmo/client/account/SecretRequest.java | 40 +++ .../nexmo/client/account/SecretResponse.java | 66 +++++ .../client/account/AccountClientTest.java | 241 +++++++++++++++++- .../account/CreateSecretMethodTest.java | 60 +++++ .../client/account/GetSecretMethodTest.java | 42 +++ .../client/account/ListSecretsMethodTest.java | 32 +++ .../account/RevokeSecretMethodTest.java | 42 +++ 18 files changed, 1141 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/nexmo/client/account/CreateSecretMethod.java create mode 100644 src/main/java/com/nexmo/client/account/CreateSecretRequest.java create mode 100644 src/main/java/com/nexmo/client/account/GetSecretMethod.java create mode 100644 src/main/java/com/nexmo/client/account/ListSecretsMethod.java create mode 100644 src/main/java/com/nexmo/client/account/ListSecretsResponse.java create mode 100644 src/main/java/com/nexmo/client/account/RevokeSecretMethod.java create mode 100644 src/main/java/com/nexmo/client/account/SecretManagementEndpoint.java create mode 100644 src/main/java/com/nexmo/client/account/SecretRequest.java create mode 100644 src/main/java/com/nexmo/client/account/SecretResponse.java create mode 100644 src/test/java/com/nexmo/client/account/CreateSecretMethodTest.java create mode 100644 src/test/java/com/nexmo/client/account/GetSecretMethodTest.java create mode 100644 src/test/java/com/nexmo/client/account/ListSecretsMethodTest.java create mode 100644 src/test/java/com/nexmo/client/account/RevokeSecretMethodTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 74e2ea0ba..58d325502 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Added `com.nexmo.client.incoming.CallEvent` to assist with the deserialization of the JSON payload used for call events. - Added `com.nexmo.client.incoming.InputEvent` to assist with the deserialization of the JSON payload used for input events. - Added `com.nexmo.client.incoming.RecordEvent` to assist with the deserialization of the JSON payload used for record events. +- Added secret management methods to `AccountClient` in the form of the following methods: + - `listSecrets` for listing all secrets. + - `getSecret` for getting information on a specific secret. + - `revokeSecret` for revoking a secret. + - `createSecret` for creating a new secret. ### Changed - User Agent String now includes the Java version in addition to the client version. diff --git a/README.md b/README.md index fc9898d16..f97ba18a4 100644 --- a/README.md +++ b/README.md @@ -272,6 +272,48 @@ NexmoClient client = new NexmoClient(auth); client.getRedactClient().redactTransaction(VOICE_ID, RedactRequest.Product.VOICE); ``` +### Create Secret + +Create a secret associated to your account id: + +```java +AuthMethod auth = new TokenAuthMethod(API_KEY, API_SECRET); +NexmoClient client = new NexmoClient(auth); +SecretResponse response = client.getAccountClient().createSecret(API_KEY, "Foo84RSecret"); +``` + +### List Secrets + +List the secret id (but not content) associated to your account id: + +```java +AuthMethod auth = new TokenAuthMethod(API_KEY, API_SECRET); +NexmoClient client = new NexmoClient(auth); +ListSecretsResponse response = client.getAccountClient().listSecrets(API_KEY); + +Collection secrets = response.getSecrets(); +``` + +### Revoke Secret + +Revoke a secret associated to your account id: + +```java +AuthMethod auth = new TokenAuthMethod(API_KEY, API_SECRET); +NexmoClient client = new NexmoClient(auth); +client.getAccountClient().revokeSecret(API_KEY, SECRET_ID); +``` + +### Retrieve Secret + +Get information about a specific secret associated to your account id: + +```java +AuthMethod auth = new TokenAuthMethod(API_KEY, API_SECRET); +NexmoClient client = new NexmoClient(auth); +SecretResponse response = client.getAccountClient().getSecret(API_KEY, SECRET_ID); +``` + ### Custom HTTP Configuration If you need to configure the Apache HttpClient used for making requests, you can diff --git a/build.gradle b/build.gradle index 731a7e3e3..816f73f15 100644 --- a/build.gradle +++ b/build.gradle @@ -52,6 +52,7 @@ dependencies { compileOnly 'javax.servlet:javax.servlet-api:3.1.0' compile 'com.fasterxml.jackson.core:jackson-databind:2.9.5' compile 'com.auth0:java-jwt:2.2.1' + compile 'io.openapitools.jackson.dataformat:jackson-dataformat-hal:1.0.4' if (Jvm.current().javaVersion.isJava9Compatible()) { // JAXB API was removed as a default module in JDK9+ this is needed for building/testing in this specific JDK. diff --git a/src/main/java/com/nexmo/client/account/AccountClient.java b/src/main/java/com/nexmo/client/account/AccountClient.java index 56cb0619f..8a440368c 100644 --- a/src/main/java/com/nexmo/client/account/AccountClient.java +++ b/src/main/java/com/nexmo/client/account/AccountClient.java @@ -29,14 +29,15 @@ import java.io.IOException; /** - * A client for talking to the Nexmo Number Insight API. The standard way to obtain an instance of this class is to use - * {@link NexmoClient#getInsightClient()}. + * A client for talking to the Nexmo Account API. The standard way to obtain an instance of this class is to use + * {@link NexmoClient#getAccountClient()} ()}. */ public class AccountClient extends AbstractClient { protected BalanceEndpoint balance; protected PricingEndpoint pricing; protected PrefixPricingEndpoint prefixPricing; protected TopUpEndpoint topUp; + protected SecretManagementEndpoint secret; /** * Constructor. @@ -50,6 +51,7 @@ public AccountClient(HttpWrapper httpWrapper) { this.pricing = new PricingEndpoint(httpWrapper); this.prefixPricing = new PrefixPricingEndpoint(httpWrapper); this.topUp = new TopUpEndpoint(httpWrapper); + this.secret = new SecretManagementEndpoint(httpWrapper); } public BalanceResponse getBalance() throws IOException, NexmoClientException { @@ -60,7 +62,9 @@ public BalanceResponse getBalance() throws IOException, NexmoClientException { * Retrieve the voice pricing for a specified country. * * @param country The two-character country code for which you would like to retrieve pricing. + * * @return PricingResponse object which contains the results from the API. + * * @throws IOException if a network error occurred contacting the Nexmo Account API. * @throws NexmoClientException if there was a problem with the Nexmo request or response objects. */ @@ -76,7 +80,9 @@ private PricingResponse getVoicePrice(PricingRequest pricingRequest) throws IOEx * Retrieve the SMS pricing for a specified country. * * @param country The two-character country code for which you would like to retrieve pricing. + * * @return PricingResponse object which contains the results from the API. + * * @throws IOException if a network error occurred contacting the Nexmo Account API. * @throws NexmoClientException if there was a problem with the Nexmo request or response objects. */ @@ -93,12 +99,13 @@ private PricingResponse getSmsPrice(PricingRequest pricingRequest) throws IOExce * * @param type The type of service to retrieve pricing for. * @param prefix The prefix to retrieve the pricing for. + * * @return PrefixPricingResponse object which contains the results from the API. + * * @throws IOException if a network error occurred contacting the Nexmo Account API. * @throws NexmoClientException if there was a problem with the Nexmo request or response objects. */ - public PrefixPricingResponse getPrefixPrice(ServiceType type, - String prefix) throws IOException, NexmoClientException { + public PrefixPricingResponse getPrefixPrice(ServiceType type, String prefix) throws IOException, NexmoClientException { return getPrefixPrice(new PrefixPricingRequest(type, prefix)); } @@ -111,6 +118,7 @@ private PrefixPricingResponse getPrefixPrice(PrefixPricingRequest prefixPricingR * reload-enabled payment. * * @param transaction The ID associated with your original auto-reload transaction + * * @throws IOException if a network error occurred contacting the Nexmo Account API. * @throws NexmoClientException if there was a problem with the Nexmo request or response object indicating that * the request was unsuccessful. @@ -122,4 +130,73 @@ public void topUp(String transaction) throws IOException, NexmoClientException { private void topUp(TopUpRequest request) throws IOException, NexmoClientException { this.topUp.topUp(request); } + + /** + * List the ID of each secret associated to the given API key. + * + * @param apiKey The API key to look up secrets for. + * + * @return ListSecretsResponse object which contains the results from the API. + * + * @throws IOException if a network error occurred contacting the Nexmo Account API + * @throws NexmoClientException if there was a problem wit hthe Nexmo request or response object indicating that the request was unsuccessful. + */ + public ListSecretsResponse listSecrets(String apiKey) throws IOException, NexmoClientException { + return this.secret.listSecrets(apiKey); + } + + /** + * Get information for a specific secret id associated to a given API key. + * + * @param apiKey The API key that the secret is associated to. + * @param secretId The id of the secret to get information on. + * + * @return SecretResponse object which contains the results from the API. + * + * @throws IOException if a network error occurred contacting the Nexmo Account API + * @throws NexmoClientException if there was a problem wit hthe Nexmo request or response object indicating that the request was unsuccessful. + */ + public SecretResponse getSecret(String apiKey, String secretId) throws IOException, NexmoClientException { + return getSecret(new SecretRequest(apiKey, secretId)); + } + + private SecretResponse getSecret(SecretRequest secretRequest) throws IOException, NexmoClientException { + return this.secret.getSecret(secretRequest); + } + + /** + * Create a secret to be used with a specific API key. + * + * @param apiKey The API key that the secret is to be used with. + * @param secret The contents of the secret. + * + * @return SecretResponse object which contains the created secret from the API. + * + * @throws IOException if a network error occurred contacting the Nexmo Account API + * @throws NexmoClientException if there was a problem wit hthe Nexmo request or response object indicating that the request was unsuccessful. + */ + public SecretResponse createSecret(String apiKey, String secret) throws IOException, NexmoClientException { + return createSecret(new CreateSecretRequest(apiKey, secret)); + } + + private SecretResponse createSecret(CreateSecretRequest createSecretRequest) throws IOException, NexmoClientException { + return this.secret.createSecret(createSecretRequest); + } + + /** + * Revoke a secret associated with a specific API key. + * + * @param apiKey The API key that the secret is associated to. + * @param secretId The id of the secret to revoke. + * + * @throws IOException if a network error occurred contacting the Nexmo Account API + * @throws NexmoClientException if there was a problem wit hthe Nexmo request or response object indicating that the request was unsuccessful. + */ + public void revokeSecret(String apiKey, String secretId) throws IOException, NexmoClientException { + revokeSecret(new SecretRequest(apiKey, secretId)); + } + + private void revokeSecret(SecretRequest secretRequest) throws IOException, NexmoClientException { + this.secret.revokeSecret(secretRequest); + } } diff --git a/src/main/java/com/nexmo/client/account/CreateSecretMethod.java b/src/main/java/com/nexmo/client/account/CreateSecretMethod.java new file mode 100644 index 000000000..c20835b2d --- /dev/null +++ b/src/main/java/com/nexmo/client/account/CreateSecretMethod.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.account; + +import com.nexmo.client.HttpWrapper; +import com.nexmo.client.NexmoBadRequestException; +import com.nexmo.client.NexmoClientException; +import com.nexmo.client.auth.SignatureAuthMethod; +import com.nexmo.client.auth.TokenAuthMethod; +import com.nexmo.client.voice.endpoints.AbstractMethod; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.BasicResponseHandler; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; + +public class CreateSecretMethod extends AbstractMethod { + private static final Class[] ALLOWED_AUTH_METHODS = new Class[]{SignatureAuthMethod.class, TokenAuthMethod.class}; + + private static final String DEFAULT_URI = "https://api.nexmo.com/accounts/%s/secrets"; + + private String uri = DEFAULT_URI; + + CreateSecretMethod(HttpWrapper httpWrapper) { + super(httpWrapper); + } + + @Override + protected Class[] getAcceptableAuthMethods() { + return ALLOWED_AUTH_METHODS; + } + + @Override + public RequestBuilder makeRequest(CreateSecretRequest createSecretRequest) throws NexmoClientException, UnsupportedEncodingException { + if (createSecretRequest.getApiKey() == null) { + throw new IllegalArgumentException("API key is required."); + } + + if (createSecretRequest.getSecret() == null) { + throw new IllegalArgumentException("Secret is required."); + } + + String uri = String.format(this.uri, createSecretRequest.getApiKey()); + return RequestBuilder + .post(uri) + .setEntity(new StringEntity(createSecretRequest.toJson(), ContentType.APPLICATION_JSON)); + } + + @Override + public SecretResponse parseResponse(HttpResponse response) throws IOException, NexmoClientException { + if (response.getStatusLine().getStatusCode() != 201) { + throw new NexmoBadRequestException(EntityUtils.toString(response.getEntity())); + } + + return SecretResponse.fromJson(new BasicResponseHandler().handleResponse(response)); + } + + @Override + protected RequestBuilder applyAuth(RequestBuilder request) throws NexmoClientException { + return getAuthMethod(getAcceptableAuthMethods()).applyAsBasicAuth(request); + } +} diff --git a/src/main/java/com/nexmo/client/account/CreateSecretRequest.java b/src/main/java/com/nexmo/client/account/CreateSecretRequest.java new file mode 100644 index 000000000..d3b2994c8 --- /dev/null +++ b/src/main/java/com/nexmo/client/account/CreateSecretRequest.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.account; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.nexmo.client.NexmoUnexpectedException; + +public class CreateSecretRequest { + @JsonIgnore + private String apiKey; + private String secret; + + public CreateSecretRequest(String apiKey, String secret) { + this.apiKey = apiKey; + this.secret = secret; + } + + public String getApiKey() { + return apiKey; + } + + public String getSecret() { + return secret; + } + + public String toJson() { + try { + ObjectMapper mapper = new ObjectMapper(); + return mapper.writeValueAsString(this); + } catch (JsonProcessingException jpe) { + throw new NexmoUnexpectedException("Failed to produce json from CreateSecretRequest object.", jpe); + } + } +} diff --git a/src/main/java/com/nexmo/client/account/GetSecretMethod.java b/src/main/java/com/nexmo/client/account/GetSecretMethod.java new file mode 100644 index 000000000..9237a304b --- /dev/null +++ b/src/main/java/com/nexmo/client/account/GetSecretMethod.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.account; + +import com.nexmo.client.HttpWrapper; +import com.nexmo.client.NexmoBadRequestException; +import com.nexmo.client.NexmoClientException; +import com.nexmo.client.auth.SignatureAuthMethod; +import com.nexmo.client.auth.TokenAuthMethod; +import com.nexmo.client.voice.endpoints.AbstractMethod; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.impl.client.BasicResponseHandler; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; + +public class GetSecretMethod extends AbstractMethod { + private static final Class[] ALLOWED_AUTH_METHODS = new Class[]{SignatureAuthMethod.class, TokenAuthMethod.class}; + + private static final String DEFAULT_URI = "https://api.nexmo.com/accounts/%s/secrets/%s"; + + private String uri = DEFAULT_URI; + + GetSecretMethod(HttpWrapper httpWrapper) { + super(httpWrapper); + } + + @Override + protected Class[] getAcceptableAuthMethods() { + return ALLOWED_AUTH_METHODS; + } + + @Override + public RequestBuilder makeRequest(SecretRequest secretRequest) throws NexmoClientException, UnsupportedEncodingException { + if (secretRequest.getApiKey() == null) { + throw new IllegalArgumentException("API key is required."); + } + + if (secretRequest.getSecretId() == null) { + throw new IllegalArgumentException("Secret id is required."); + } + + String uri = String.format(this.uri, secretRequest.getApiKey(), secretRequest.getSecretId()); + return RequestBuilder.get(uri); + } + + @Override + public SecretResponse parseResponse(HttpResponse response) throws IOException, NexmoClientException { + if (response.getStatusLine().getStatusCode() != 200) { + throw new NexmoBadRequestException(EntityUtils.toString(response.getEntity())); + } + + return SecretResponse.fromJson(new BasicResponseHandler().handleResponse(response)); + } + + @Override + protected RequestBuilder applyAuth(RequestBuilder request) throws NexmoClientException { + return getAuthMethod(getAcceptableAuthMethods()).applyAsBasicAuth(request); + } +} diff --git a/src/main/java/com/nexmo/client/account/ListSecretsMethod.java b/src/main/java/com/nexmo/client/account/ListSecretsMethod.java new file mode 100644 index 000000000..13b171b08 --- /dev/null +++ b/src/main/java/com/nexmo/client/account/ListSecretsMethod.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.account; + +import com.nexmo.client.HttpWrapper; +import com.nexmo.client.NexmoBadRequestException; +import com.nexmo.client.NexmoClientException; +import com.nexmo.client.auth.SignatureAuthMethod; +import com.nexmo.client.auth.TokenAuthMethod; +import com.nexmo.client.voice.endpoints.AbstractMethod; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.impl.client.BasicResponseHandler; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; + +public class ListSecretsMethod extends AbstractMethod { + private static final Class[] ALLOWED_AUTH_METHODS = new Class[]{SignatureAuthMethod.class, TokenAuthMethod.class}; + + private static final String DEFAULT_URI = "https://api.nexmo.com/accounts/%s/secrets"; + + private String uri = DEFAULT_URI; + + ListSecretsMethod(HttpWrapper httpWrapper) { + super(httpWrapper); + } + + @Override + protected Class[] getAcceptableAuthMethods() { + return ALLOWED_AUTH_METHODS; + } + + @Override + public RequestBuilder makeRequest(String apiKey) throws NexmoClientException, UnsupportedEncodingException { + if (apiKey == null) { + throw new IllegalArgumentException("API key is required."); + } + + String uri = String.format(this.uri, apiKey); + return RequestBuilder.get(uri); + } + + @Override + public ListSecretsResponse parseResponse(HttpResponse response) throws IOException, NexmoClientException { + if (response.getStatusLine().getStatusCode() != 200) { + throw new NexmoBadRequestException(EntityUtils.toString(response.getEntity())); + } + + return ListSecretsResponse.fromJson(new BasicResponseHandler().handleResponse(response)); + } + + @Override + protected RequestBuilder applyAuth(RequestBuilder request) throws NexmoClientException { + return getAuthMethod(getAcceptableAuthMethods()).applyAsBasicAuth(request); + } +} diff --git a/src/main/java/com/nexmo/client/account/ListSecretsResponse.java b/src/main/java/com/nexmo/client/account/ListSecretsResponse.java new file mode 100644 index 000000000..f9ea41296 --- /dev/null +++ b/src/main/java/com/nexmo/client/account/ListSecretsResponse.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.account; + +import com.nexmo.client.NexmoUnexpectedException; +import io.openapitools.jackson.dataformat.hal.HALLink; +import io.openapitools.jackson.dataformat.hal.HALMapper; +import io.openapitools.jackson.dataformat.hal.annotation.EmbeddedResource; +import io.openapitools.jackson.dataformat.hal.annotation.Link; +import io.openapitools.jackson.dataformat.hal.annotation.Resource; + +import java.io.IOException; +import java.util.Collection; + +@Resource +public class ListSecretsResponse { + @Link + private HALLink self; + + @EmbeddedResource + private Collection secrets; + + public HALLink getSelf() { + return self; + } + + public Collection getSecrets() { + return secrets; + } + + public static ListSecretsResponse fromJson(String json) { + try { + return new HALMapper().readValue(json, ListSecretsResponse.class); + } catch (IOException e) { + throw new NexmoUnexpectedException("Failed to produce ListSecretsResponse from json.", e); + } + } +} diff --git a/src/main/java/com/nexmo/client/account/RevokeSecretMethod.java b/src/main/java/com/nexmo/client/account/RevokeSecretMethod.java new file mode 100644 index 000000000..953194a69 --- /dev/null +++ b/src/main/java/com/nexmo/client/account/RevokeSecretMethod.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.account; + +import com.nexmo.client.HttpWrapper; +import com.nexmo.client.NexmoBadRequestException; +import com.nexmo.client.NexmoClientException; +import com.nexmo.client.auth.SignatureAuthMethod; +import com.nexmo.client.auth.TokenAuthMethod; +import com.nexmo.client.voice.endpoints.AbstractMethod; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; + +public class RevokeSecretMethod extends AbstractMethod { + private static final Class[] ALLOWED_AUTH_METHODS = new Class[]{SignatureAuthMethod.class, TokenAuthMethod.class}; + + private static final String DEFAULT_URI = "https://api.nexmo.com/accounts/%s/secrets/%s"; + + private String uri = DEFAULT_URI; + + RevokeSecretMethod(HttpWrapper httpWrapper) { + super(httpWrapper); + } + + @Override + protected Class[] getAcceptableAuthMethods() { + return ALLOWED_AUTH_METHODS; + } + + @Override + public RequestBuilder makeRequest(SecretRequest secretRequest) throws NexmoClientException, UnsupportedEncodingException { + if (secretRequest.getApiKey() == null) { + throw new IllegalArgumentException("API key is required."); + } + + if (secretRequest.getSecretId() == null) { + throw new IllegalArgumentException("Secret id is required."); + } + + String uri = String.format(this.uri, secretRequest.getApiKey(), secretRequest.getSecretId()); + return RequestBuilder.delete(uri); + } + + @Override + public Void parseResponse(HttpResponse response) throws IOException, NexmoClientException { + if (response.getStatusLine().getStatusCode() != 204) { + throw new NexmoBadRequestException(EntityUtils.toString(response.getEntity())); + } + + return null; + } + + @Override + protected RequestBuilder applyAuth(RequestBuilder request) throws NexmoClientException { + return getAuthMethod(getAcceptableAuthMethods()).applyAsBasicAuth(request); + } +} diff --git a/src/main/java/com/nexmo/client/account/SecretManagementEndpoint.java b/src/main/java/com/nexmo/client/account/SecretManagementEndpoint.java new file mode 100644 index 000000000..0d6d0f1a7 --- /dev/null +++ b/src/main/java/com/nexmo/client/account/SecretManagementEndpoint.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.account; + +import com.nexmo.client.HttpWrapper; +import com.nexmo.client.NexmoClientException; + +import java.io.IOException; + +class SecretManagementEndpoint { + private ListSecretsMethod listSecretsMethod; + private GetSecretMethod getSecretMethod; + private CreateSecretMethod createSecretMethod; + private RevokeSecretMethod revokeSecretMethod; + + SecretManagementEndpoint(HttpWrapper httpWrapper) { + this.listSecretsMethod = new ListSecretsMethod(httpWrapper); + this.getSecretMethod = new GetSecretMethod(httpWrapper); + this.createSecretMethod = new CreateSecretMethod(httpWrapper); + this.revokeSecretMethod = new RevokeSecretMethod(httpWrapper); + + } + + ListSecretsResponse listSecrets(String apiKey) throws IOException, NexmoClientException { + return this.listSecretsMethod.execute(apiKey); + } + + SecretResponse getSecret(SecretRequest secretRequest) throws IOException, NexmoClientException { + return this.getSecretMethod.execute(secretRequest); + } + + SecretResponse createSecret(CreateSecretRequest createSecretRequest) throws IOException, NexmoClientException { + return this.createSecretMethod.execute(createSecretRequest); + } + + void revokeSecret(SecretRequest secretRequest) throws IOException, NexmoClientException { + this.revokeSecretMethod.execute(secretRequest); + } +} diff --git a/src/main/java/com/nexmo/client/account/SecretRequest.java b/src/main/java/com/nexmo/client/account/SecretRequest.java new file mode 100644 index 000000000..72e9816d9 --- /dev/null +++ b/src/main/java/com/nexmo/client/account/SecretRequest.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.account; + +public class SecretRequest { + private String apiKey; + private String secretId; + + public SecretRequest(String apiKey, String secretId) { + this.apiKey = apiKey; + this.secretId = secretId; + } + + public String getApiKey() { + return apiKey; + } + + public String getSecretId() { + return secretId; + } +} diff --git a/src/main/java/com/nexmo/client/account/SecretResponse.java b/src/main/java/com/nexmo/client/account/SecretResponse.java new file mode 100644 index 000000000..13c2f3661 --- /dev/null +++ b/src/main/java/com/nexmo/client/account/SecretResponse.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.account; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.nexmo.client.NexmoUnexpectedException; +import io.openapitools.jackson.dataformat.hal.HALLink; +import io.openapitools.jackson.dataformat.hal.HALMapper; +import io.openapitools.jackson.dataformat.hal.annotation.Link; +import io.openapitools.jackson.dataformat.hal.annotation.Resource; + +import java.io.IOException; +import java.util.Date; + +@Resource +public class SecretResponse { + @Link + private HALLink self; + + private String id; + + @JsonProperty("created_at") + private Date created; + + public HALLink getSelf() { + return self; + } + + public String getId() { + return id; + } + + public Date getCreated() { + return created; + } + + public static SecretResponse fromJson(String json) { + try { + HALMapper mapper = new HALMapper(); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + return mapper.readValue(json, SecretResponse.class); + } catch (IOException e) { + throw new NexmoUnexpectedException("Failed to produce SecretResponse from json.", e); + } + } +} diff --git a/src/test/java/com/nexmo/client/account/AccountClientTest.java b/src/test/java/com/nexmo/client/account/AccountClientTest.java index 479ba8728..0c06fa20a 100644 --- a/src/test/java/com/nexmo/client/account/AccountClientTest.java +++ b/src/test/java/com/nexmo/client/account/AccountClientTest.java @@ -30,7 +30,11 @@ import org.junit.Test; import java.math.BigDecimal; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.TimeZone; +import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.*; public class AccountClientTest extends ClientTest { @@ -54,7 +58,16 @@ public void testGetBalance() throws Exception { @Test public void testGetSmsPrice() throws Exception { - String json = "{\n" + " \"dialingPrefix\": \"1\",\n" + " \"defaultPrice\": \"0.00570000\",\n" + " \"currency\": \"EUR\",\n" + " \"countryDisplayName\": \"United States of America\",\n" + " \"countryCode\": \"US\",\n" + " \"countryName\": \"United States\",\n" + " \"networks\": [\n" + " {\n" + " \"type\": \"mobile\",\n" + " \"price\": \"0.00570000\",\n" + " \"currency\": \"EUR\",\n" + " \"mcc\": \"987\",\n" + " \"mnc\": \"123\",\n" + " \"networkCode\": \"123456\",\n" + " \"networkName\": \"Test Mobile\"\n" + " },\n" + " {\n" + " \"type\": \"landline\",\n" + " \"price\": \"0.00330000\",\n" + " \"currency\": \"EUR\",\n" + " \"mcc\": \"123\",\n" + " \"mnc\": \"456\",\n" + " \"networkCode\": \"networkcode\",\n" + " \"networkName\": \"Test Landline\"\n" + " } \n" + " ]\n" + "}\n"; + String json = "{\n" + " \"dialingPrefix\": \"1\",\n" + " \"defaultPrice\": \"0.00570000\",\n" + + " \"currency\": \"EUR\",\n" + " \"countryDisplayName\": \"United States of America\",\n" + + " \"countryCode\": \"US\",\n" + " \"countryName\": \"United States\",\n" + " \"networks\": [\n" + + " {\n" + " \"type\": \"mobile\",\n" + " \"price\": \"0.00570000\",\n" + + " \"currency\": \"EUR\",\n" + " \"mcc\": \"987\",\n" + " \"mnc\": \"123\",\n" + + " \"networkCode\": \"123456\",\n" + " \"networkName\": \"Test Mobile\"\n" + " },\n" + + " {\n" + " \"type\": \"landline\",\n" + " \"price\": \"0.00330000\",\n" + + " \"currency\": \"EUR\",\n" + " \"mcc\": \"123\",\n" + " \"mnc\": \"456\",\n" + + " \"networkCode\": \"networkcode\",\n" + " \"networkName\": \"Test Landline\"\n" + + " } \n" + " ]\n" + "}\n"; wrapper.setHttpClient(this.stubHttpClient(200, json)); PricingResponse response = client.getSmsPrice("US"); Assert.assertEquals("1", response.getDialingPrefix()); @@ -87,7 +100,16 @@ public void testGetSmsPrice() throws Exception { @Test public void testGetVoicePrice() throws Exception { - String json = "{\n" + " \"dialingPrefix\": \"1\",\n" + " \"defaultPrice\": \"0.00570000\",\n" + " \"currency\": \"EUR\",\n" + " \"countryDisplayName\": \"United States of America\",\n" + " \"countryCode\": \"US\",\n" + " \"countryName\": \"United States\",\n" + " \"networks\": [\n" + " {\n" + " \"type\": \"mobile\",\n" + " \"price\": \"0.00570000\",\n" + " \"currency\": \"EUR\",\n" + " \"mcc\": \"987\",\n" + " \"mnc\": \"123\",\n" + " \"networkCode\": \"123456\",\n" + " \"networkName\": \"Test Mobile\"\n" + " },\n" + " {\n" + " \"type\": \"landline\",\n" + " \"price\": \"0.00330000\",\n" + " \"currency\": \"EUR\",\n" + " \"mcc\": \"123\",\n" + " \"mnc\": \"456\",\n" + " \"networkCode\": \"networkcode\",\n" + " \"networkName\": \"Test Landline\"\n" + " } \n" + " ]\n" + "}\n"; + String json = "{\n" + " \"dialingPrefix\": \"1\",\n" + " \"defaultPrice\": \"0.00570000\",\n" + + " \"currency\": \"EUR\",\n" + " \"countryDisplayName\": \"United States of America\",\n" + + " \"countryCode\": \"US\",\n" + " \"countryName\": \"United States\",\n" + " \"networks\": [\n" + + " {\n" + " \"type\": \"mobile\",\n" + " \"price\": \"0.00570000\",\n" + + " \"currency\": \"EUR\",\n" + " \"mcc\": \"987\",\n" + " \"mnc\": \"123\",\n" + + " \"networkCode\": \"123456\",\n" + " \"networkName\": \"Test Mobile\"\n" + " },\n" + + " {\n" + " \"type\": \"landline\",\n" + " \"price\": \"0.00330000\",\n" + + " \"currency\": \"EUR\",\n" + " \"mcc\": \"123\",\n" + " \"mnc\": \"456\",\n" + + " \"networkCode\": \"networkcode\",\n" + " \"networkName\": \"Test Landline\"\n" + + " } \n" + " ]\n" + "}\n"; wrapper.setHttpClient(this.stubHttpClient(200, json)); PricingResponse response = client.getVoicePrice("US"); Assert.assertEquals("1", response.getDialingPrefix()); @@ -120,7 +142,27 @@ public void testGetVoicePrice() throws Exception { @Test public void testGetPrefixVoicePrice() throws Exception { - String json = "{\n" + " \"count\": 2,\n" + " \"countries\": [\n" + " {\n" + " \"dialingPrefix\": \"1\",\n" + " \"defaultPrice\": \"0.01270000\",\n" + " \"currency\": \"EUR\",\n" + " \"countryDisplayName\": \"Canada\",\n" + " \"countryCode\": \"CA\",\n" + " \"countryName\": \"Canada\",\n" + " \"networks\": [\n" + " {\n" + " \"type\": \"mobile\",\n" + " \"price\": \"0.01280000\",\n" + " \"currency\": \"EUR\",\n" + " \"aliases\": [\n" + " \"302998\"\n" + " ],\n" + " \"mcc\": \"302\",\n" + " \"mnc\": \"702\",\n" + " \"networkCode\": \"302702\",\n" + " \"networkName\": \"BELL ALIANT REGIONAL Communications LP\"\n" + " },\n" + " {\n" + " \"type\": \"landline\",\n" + " \"price\": \"0.01000000\",\n" + " \"currency\": \"EUR\",\n" + " \"networkCode\": \"CA-FIXED\",\n" + " \"networkName\": \"Canada Landline\"\n" + " }\n" + " ]\n" + " },\n" + " {\n" + " \"dialingPrefix\": \"1\",\n" + " \"currency\": \"EUR\",\n" + " \"countryDisplayName\": \"United States Minor Outlying Islands\",\n" + " \"countryCode\": \"UM\",\n" + " \"countryName\": \"United States Minor Outlying Islands\"\n" + " }\n" + " ]\n" + "}"; + String json = "{\n" + " \"count\": 2,\n" + " \"countries\": [\n" + " {\n" + + " \"dialingPrefix\": \"1\",\n" + " \"defaultPrice\": \"0.01270000\",\n" + + " \"currency\": \"EUR\",\n" + " \"countryDisplayName\": \"Canada\",\n" + + " \"countryCode\": \"CA\",\n" + " \"countryName\": \"Canada\",\n" + + " \"networks\": [\n" + " {\n" + + " \"type\": \"mobile\",\n" + " \"price\": \"0.01280000\",\n" + + " \"currency\": \"EUR\",\n" + " \"aliases\": [\n" + + " \"302998\"\n" + " ],\n" + + " \"mcc\": \"302\",\n" + " \"mnc\": \"702\",\n" + + " \"networkCode\": \"302702\",\n" + + " \"networkName\": \"BELL ALIANT REGIONAL Communications LP\"\n" + + " },\n" + " {\n" + " \"type\": \"landline\",\n" + + " \"price\": \"0.01000000\",\n" + " \"currency\": \"EUR\",\n" + + " \"networkCode\": \"CA-FIXED\",\n" + + " \"networkName\": \"Canada Landline\"\n" + " }\n" + + " ]\n" + " },\n" + " {\n" + " \"dialingPrefix\": \"1\",\n" + + " \"currency\": \"EUR\",\n" + + " \"countryDisplayName\": \"United States Minor Outlying Islands\",\n" + + " \"countryCode\": \"UM\",\n" + + " \"countryName\": \"United States Minor Outlying Islands\"\n" + " }\n" + " ]\n" + + "}"; wrapper.setHttpClient(this.stubHttpClient(200, json)); PrefixPricingResponse response = client.getPrefixPrice(ServiceType.VOICE, "1"); Assert.assertEquals(2, response.getCount()); @@ -162,7 +204,23 @@ public void testGetPrefixVoicePrice() throws Exception { @Test public void testGetPrefixSmsPrice() throws Exception { - String json = "{\n" + " \"count\": 2,\n" + " \"countries\": [\n" + " {\n" + " \"dialingPrefix\": \"1\",\n" + " \"defaultPrice\": \"0.00570000\",\n" + " \"currency\": \"EUR\",\n" + " \"countryDisplayName\": \"Canada\",\n" + " \"countryCode\": \"CA\",\n" + " \"countryName\": \"Canada\",\n" + " \"networks\": [\n" + " {\n" + " \"type\": \"mobile\",\n" + " \"price\": \"0.00570000\",\n" + " \"currency\": \"EUR\",\n" + " \"aliases\": [\n" + " \"302660\"\n" + " ],\n" + " \"mcc\": \"302\",\n" + " \"mnc\": \"655\",\n" + " \"networkCode\": \"302655\",\n" + " \"networkName\": \"MTS Communications Inc.\"\n" + " }\n" + " ]\n" + " },\n" + " {\n" + " \"dialingPrefix\": \"1\",\n" + " \"currency\": \"EUR\",\n" + " \"countryDisplayName\": \"United States Minor Outlying Islands\",\n" + " \"countryCode\": \"UM\",\n" + " \"countryName\": \"United States Minor Outlying Islands\"\n" + " }\n" + " ]\n" + "}"; + String json = "{\n" + " \"count\": 2,\n" + " \"countries\": [\n" + " {\n" + + " \"dialingPrefix\": \"1\",\n" + " \"defaultPrice\": \"0.00570000\",\n" + + " \"currency\": \"EUR\",\n" + " \"countryDisplayName\": \"Canada\",\n" + + " \"countryCode\": \"CA\",\n" + " \"countryName\": \"Canada\",\n" + + " \"networks\": [\n" + " {\n" + + " \"type\": \"mobile\",\n" + " \"price\": \"0.00570000\",\n" + + " \"currency\": \"EUR\",\n" + " \"aliases\": [\n" + + " \"302660\"\n" + " ],\n" + + " \"mcc\": \"302\",\n" + " \"mnc\": \"655\",\n" + + " \"networkCode\": \"302655\",\n" + + " \"networkName\": \"MTS Communications Inc.\"\n" + " }\n" + + " ]\n" + " },\n" + " {\n" + " \"dialingPrefix\": \"1\",\n" + + " \"currency\": \"EUR\",\n" + + " \"countryDisplayName\": \"United States Minor Outlying Islands\",\n" + + " \"countryCode\": \"UM\",\n" + + " \"countryName\": \"United States Minor Outlying Islands\"\n" + " }\n" + " ]\n" + + "}"; wrapper.setHttpClient(this.stubHttpClient(200, json)); PrefixPricingResponse response = client.getPrefixPrice(ServiceType.SMS, "1"); Assert.assertEquals(2, response.getCount()); @@ -214,4 +272,179 @@ public void testTopUpFailed() throws Exception { wrapper.setHttpClient(this.stubHttpClient(401, json)); client.topUp("ABC123"); } + + @Test + public void testListSecretSuccessful() throws Exception { + String json = "{\n" + " \"_links\": {\n" + " \"self\": {\n" + + " \"href\": \"/accounts/abcd1234/secrets\"\n" + " }\n" + " },\n" + + " \"_embedded\": {\n" + " \"secrets\": [\n" + " {\n" + + " \"_links\": {\n" + " \"self\": {\n" + + " \"href\": \"/accounts/abcd1234/secrets/secret-id-one\"\n" + + " }\n" + " },\n" + " \"id\": \"secret-id-one\",\n" + + " \"created_at\": \"2017-03-02T16:34:49Z\"\n" + " },\n" + " {\n" + + " \"_links\": {\n" + " \"self\": {\n" + + " \"href\": \"/accounts/abcd1234/secrets/secret-id-two\"\n" + + " }\n" + " },\n" + " \"id\": \"secret-id-two\",\n" + + " \"created_at\": \"2016-01-20T16:34:49Z\"\n" + " }\n" + " ]\n" + + " }\n" + "}"; + wrapper.setHttpClient(this.stubHttpClient(200, json)); + + ListSecretsResponse response = client.listSecrets("abcd1234"); + SecretResponse[] responses = response.getSecrets().toArray(new SecretResponse[0]); + + Calendar calendar = new GregorianCalendar(2017, Calendar.MARCH, 2, 16, 34, 49); + calendar.setTimeZone(TimeZone.getTimeZone("UTC")); + assertEquals("secret-id-one", responses[0].getId()); + assertEquals(calendar.getTime(), responses[0].getCreated()); + assertEquals("/accounts/abcd1234/secrets/secret-id-one", responses[0].getSelf().getHref()); + + calendar.set(2016, Calendar.JANUARY, 20, 16, 34, 49); + assertEquals("secret-id-two", responses[1].getId()); + assertEquals(calendar.getTime(), responses[1].getCreated()); + assertEquals("/accounts/abcd1234/secrets/secret-id-two", responses[1].getSelf().getHref()); + } + + @Test(expected = NexmoClientException.class) + public void testListSecretFailedAuth() throws Exception { + String json = "{\n" + " \"type\": \"https://developer.nexmo.com/api-errors#unauthorized\",\n" + + " \"title\": \"Invalid credentials supplied\",\n" + + " \"detail\": \"You did not provide correct credentials.\",\n" + + " \"instance\": \"797a8f199c45014ab7b08bfe9cc1c12c\"\n" + "}"; + wrapper.setHttpClient(this.stubHttpClient(401, json)); + client.listSecrets("ABC123"); + } + + @Test(expected = NexmoClientException.class) + public void testListSecretNotFound() throws Exception { + String json = "{\n" + " \"type\": \"https://developer.nexmo.com/api-errors#invalid-api-key\",\n" + + " \"title\": \"Invalid API Key\",\n" + + " \"detail\": \"API key 'ABC123' does not exist, or you do not have access\",\n" + + " \"instance\": \"797a8f199c45014ab7b08bfe9cc1c12c\"\n" + "}"; + wrapper.setHttpClient(this.stubHttpClient(404, json)); + client.listSecrets("ABC123"); + } + + @Test + public void testCreateSecretSuccessful() throws Exception { + String json = "{\n" + " \"_links\": {\n" + " \"self\": {\n" + + " \"href\": \"/accounts/abcd1234/secrets/secret-id-one\"\n" + " }\n" + " },\n" + + " \"id\": \"secret-id-one\",\n" + " \"created_at\": \"2017-03-02T16:34:49Z\"\n" + "}"; + wrapper.setHttpClient(this.stubHttpClient(201, json)); + + SecretResponse response = client.createSecret("apiKey", "secret"); + + Calendar calendar = new GregorianCalendar(2017, Calendar.MARCH, 2, 16, 34, 49); + calendar.setTimeZone(TimeZone.getTimeZone("UTC")); + assertEquals("secret-id-one", response.getId()); + assertEquals(calendar.getTime(), response.getCreated()); + assertEquals("/accounts/abcd1234/secrets/secret-id-one", response.getSelf().getHref()); + } + + @Test(expected = NexmoClientException.class) + public void testCreateSecretBadRequest() throws Exception { + String json = + "{\n" + " \"type\": \"https://developer.nexmo.com/api-errors/account/secret-management#validation\",\n" + + " \"title\": \"Bad Request\",\n" + + " \"detail\": \"The request failed due to validation errors\",\n" + + " \"invalid_parameters\": [\n" + " {\n" + " \"name\": \"secret\",\n" + + " \"reason\": \"Does not meet complexity requirements\"\n" + " }\n" + " ],\n" + + " \"instance\": \"797a8f199c45014ab7b08bfe9cc1c12c\"\n" + "}"; + wrapper.setHttpClient(this.stubHttpClient(400, json)); + client.createSecret("key", "secret"); + } + + @Test(expected = NexmoClientException.class) + public void testCreateSecretFailedAuth() throws Exception { + String json = "{\n" + " \"type\": \"https://developer.nexmo.com/api-errors#unauthorized\",\n" + + " \"title\": \"Invalid credentials supplied\",\n" + + " \"detail\": \"You did not provide correct credentials.\",\n" + + " \"instance\": \"797a8f199c45014ab7b08bfe9cc1c12c\"\n" + "}"; + wrapper.setHttpClient(this.stubHttpClient(401, json)); + client.createSecret("key", "secret"); + } + + @Test(expected = NexmoClientException.class) + public void testCreateSecretMaxSecrets() throws Exception { + String json = "{\n" + + " \"type\": \"https://developer.nexmo.com/api-errors/account/secret-management#maximum-secrets-allowed\",\n" + + " \"title\": \"Maxmimum number of secrets already met\",\n" + + " \"detail\": \"This account has reached maximum number of '2' allowed secrets\",\n" + + " \"instance\": \"797a8f199c45014ab7b08bfe9cc1c12c\"\n" + "}"; + wrapper.setHttpClient(this.stubHttpClient(403, json)); + client.createSecret("key", "secret"); + } + + @Test(expected = NexmoClientException.class) + public void testCreateSecretAccountNotFound() throws Exception { + String json = "{\n" + " \"type\": \"https://developer.nexmo.com/api-errors#invalid-api-key\",\n" + + " \"title\": \"Invalid API Key\",\n" + + " \"detail\": \"API key 'ABC123' does not exist, or you do not have access\",\n" + + " \"instance\": \"797a8f199c45014ab7b08bfe9cc1c12c\"\n" + "}"; + wrapper.setHttpClient(this.stubHttpClient(404, json)); + client.createSecret("key", "secret"); + } + + @Test + public void testGetSecretSuccessful() throws Exception { + String json = "{\n" + " \"_links\": {\n" + " \"self\": {\n" + + " \"href\": \"/accounts/abcd1234/secrets/secret-id-one\"\n" + " }\n" + " },\n" + + " \"id\": \"secret-id-one\",\n" + " \"created_at\": \"2017-03-02T16:34:49Z\"\n" + "}"; + wrapper.setHttpClient(this.stubHttpClient(200, json)); + + SecretResponse response = client.getSecret("apiKey", "secret-id-one"); + + Calendar calendar = new GregorianCalendar(2017, Calendar.MARCH, 2, 16, 34, 49); + calendar.setTimeZone(TimeZone.getTimeZone("UTC")); + assertEquals("secret-id-one", response.getId()); + assertEquals(calendar.getTime(), response.getCreated()); + assertEquals("/accounts/abcd1234/secrets/secret-id-one", response.getSelf().getHref()); + } + + @Test(expected = NexmoClientException.class) + public void testGetSecretFailedAuth() throws Exception { + String json = "{\n" + " \"type\": \"https://developer.nexmo.com/api-errors#unauthorized\",\n" + + " \"title\": \"Invalid credentials supplied\",\n" + + " \"detail\": \"You did not provide correct credentials.\",\n" + + " \"instance\": \"797a8f199c45014ab7b08bfe9cc1c12c\"\n" + "}"; + wrapper.setHttpClient(this.stubHttpClient(401, json)); + client.getSecret("apiKey", "secret-id-one"); + } + + @Test(expected = NexmoClientException.class) + public void testGetSecretNotFound() throws Exception { + String json = "{\n" + " \"type\": \"https://developer.nexmo.com/api-errors#invalid-api-key\",\n" + + " \"title\": \"Invalid API Key\",\n" + + " \"detail\": \"API key 'ABC123' does not exist, or you do not have access\",\n" + + " \"instance\": \"797a8f199c45014ab7b08bfe9cc1c12c\"\n" + "}"; + wrapper.setHttpClient(this.stubHttpClient(404, json)); + client.getSecret("apiKey", "secret-id-one"); + } + + @Test + public void testRevokeSecretSuccessful() throws Exception { + wrapper.setHttpClient(this.stubHttpClient(204, "")); + // No assertions as an exception will be thrown if failure occurs. + client.revokeSecret("apiKey", "secretId"); + } + + @Test(expected = NexmoClientException.class) + public void testRevokeSecretFailedAuth() throws Exception { + String json = "{\n" + " \"type\": \"https://developer.nexmo.com/api-errors#unauthorized\",\n" + + " \"title\": \"Invalid credentials supplied\",\n" + + " \"detail\": \"You did not provide correct credentials.\",\n" + + " \"instance\": \"797a8f199c45014ab7b08bfe9cc1c12c\"\n" + "}"; + wrapper.setHttpClient(this.stubHttpClient(401, json)); + client.revokeSecret("apiKey", "secret-id-one"); + } + + @Test(expected = NexmoClientException.class) + public void testRevokeSecretForbidden() throws Exception { + String json = "{\n" + + " \"type\": \"https://developer.nexmo.com/api-errors/account/secret-management#delete-last-secret\",\n" + + " \"title\": \"Secret Deletion Forbidden\",\n" + + " \"detail\": \"Can not delete the last secret. The account must always have at least 1 secret active at any time\",\n" + + " \"instance\": \"797a8f199c45014ab7b08bfe9cc1c12c\"\n" + "}"; + wrapper.setHttpClient(this.stubHttpClient(403, json)); + client.revokeSecret("apiKey", "secret-id-one"); + } } diff --git a/src/test/java/com/nexmo/client/account/CreateSecretMethodTest.java b/src/test/java/com/nexmo/client/account/CreateSecretMethodTest.java new file mode 100644 index 000000000..5a7bfc539 --- /dev/null +++ b/src/test/java/com/nexmo/client/account/CreateSecretMethodTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.account; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.entity.ContentType; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class CreateSecretMethodTest { + @Test + public void testConstructParams() throws Exception { + CreateSecretMethod method = new CreateSecretMethod(null); + CreateSecretRequest request = new CreateSecretRequest("account-id", "secret"); + + RequestBuilder builder = method.makeRequest(request); + HttpEntity entity = builder.getEntity(); + + assertEquals(entity.getContentType().getValue(), ContentType.APPLICATION_JSON.toString()); + assertNotNull(entity.getContent()); + } + + @Test(expected = IllegalArgumentException.class) + public void testConstructParamsWithMissingApiKey() throws Exception { + CreateSecretMethod method = new CreateSecretMethod(null); + CreateSecretRequest request = new CreateSecretRequest(null, "secret"); + + method.makeRequest(request); + } + + @Test(expected = IllegalArgumentException.class) + public void testConstructParamsWithMissingSecret() throws Exception { + CreateSecretMethod method = new CreateSecretMethod(null); + CreateSecretRequest request = new CreateSecretRequest("account-id", null); + + method.makeRequest(request); + } +} diff --git a/src/test/java/com/nexmo/client/account/GetSecretMethodTest.java b/src/test/java/com/nexmo/client/account/GetSecretMethodTest.java new file mode 100644 index 000000000..754696305 --- /dev/null +++ b/src/test/java/com/nexmo/client/account/GetSecretMethodTest.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.account; + +import org.junit.Test; + +public class GetSecretMethodTest { + @Test(expected = IllegalArgumentException.class) + public void testConstructParamsWithMissingApiKey() throws Exception { + GetSecretMethod method = new GetSecretMethod(null); + SecretRequest request = new SecretRequest(null, "secret-id"); + + method.makeRequest(request); + } + + @Test(expected = IllegalArgumentException.class) + public void testConstructParamsWithMissingSecretId() throws Exception { + GetSecretMethod method = new GetSecretMethod(null); + SecretRequest request = new SecretRequest("api-key", null); + + method.makeRequest(request); + } +} diff --git a/src/test/java/com/nexmo/client/account/ListSecretsMethodTest.java b/src/test/java/com/nexmo/client/account/ListSecretsMethodTest.java new file mode 100644 index 000000000..b49e45348 --- /dev/null +++ b/src/test/java/com/nexmo/client/account/ListSecretsMethodTest.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.account; + +import org.junit.Test; + +public class ListSecretsMethodTest { + @Test(expected = IllegalArgumentException.class) + public void testConstructParamsWithMissingApiKey() throws Exception { + ListSecretsMethod method = new ListSecretsMethod(null); + method.makeRequest(null); + } +} diff --git a/src/test/java/com/nexmo/client/account/RevokeSecretMethodTest.java b/src/test/java/com/nexmo/client/account/RevokeSecretMethodTest.java new file mode 100644 index 000000000..e4d67a52f --- /dev/null +++ b/src/test/java/com/nexmo/client/account/RevokeSecretMethodTest.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2011-2018 Nexmo Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.nexmo.client.account; + +import org.junit.Test; + +public class RevokeSecretMethodTest { + @Test(expected = IllegalArgumentException.class) + public void testConstructParamsWithMissingApiKey() throws Exception { + RevokeSecretMethod method = new RevokeSecretMethod(null); + SecretRequest request = new SecretRequest(null, "secret-id"); + + method.makeRequest(request); + } + + @Test(expected = IllegalArgumentException.class) + public void testConstructParamsWithMissingSecretId() throws Exception { + RevokeSecretMethod method = new RevokeSecretMethod(null); + SecretRequest request = new SecretRequest("account-id", null); + + method.makeRequest(request); + } +} From c517e247b302513b7e662dee8d6b4e35c6cd8722 Mon Sep 17 00:00:00 2001 From: Steve Crow Date: Wed, 19 Sep 2018 10:39:02 -0400 Subject: [PATCH 7/8] Add version to changelog. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58d325502..80ac11c36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [Development] +## [3.8.0] - 2018-09-19 ### Added - Added `com.nexmo.client.incoming.MessageEvent` to assist with the deserialization of the JSON payload used for incoming messages. - Added `com.nexmo.client.incoming.CallEvent` to assist with the deserialization of the JSON payload used for call events. From fb9ed50bda2cf7aae37ebb67a94ae92511e0633a Mon Sep 17 00:00:00 2001 From: Steve Crow Date: Wed, 19 Sep 2018 10:39:08 -0400 Subject: [PATCH 8/8] =?UTF-8?q?Bump=20version:=203.7.0=20=E2=86=92=203.8.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- README.md | 4 ++-- build.gradle | 2 +- src/main/java/com/nexmo/client/HttpWrapper.java | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 74dca4ab3..f0cc00414 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,7 +1,7 @@ [bumpversion] commit = True tag = True -current_version = 3.7.0 +current_version = 3.8.0 parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\-(?P[a-z]+))? serialize = {major}.{minor}.{patch} diff --git a/README.md b/README.md index f97ba18a4..c0a3bce62 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ repositories { } dependencies { - compile 'com.nexmo:client:3.7.0' + compile 'com.nexmo:client:3.8.0' } ``` @@ -40,7 +40,7 @@ Add the following to the correct place in your project's POM file: com.nexmo client - 3.7.0 + 3.8.0 ``` diff --git a/build.gradle b/build.gradle index 816f73f15..8e860110f 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ apply plugin: 'eclipse' group = "com.nexmo" archivesBaseName = "client" -version = "3.7.0" +version = "3.8.0" sourceCompatibility = "1.7" targetCompatibility = "1.7" diff --git a/src/main/java/com/nexmo/client/HttpWrapper.java b/src/main/java/com/nexmo/client/HttpWrapper.java index 93ba085bb..1e5f7d007 100644 --- a/src/main/java/com/nexmo/client/HttpWrapper.java +++ b/src/main/java/com/nexmo/client/HttpWrapper.java @@ -37,7 +37,7 @@ */ public class HttpWrapper { private static final String CLIENT_NAME = "nexmo-java"; - private static final String CLIENT_VERSION = "3.7.0"; + private static final String CLIENT_VERSION = "3.8.0"; private static final String JAVA_VERSION = System.getProperty("java.version"); private AuthCollection authCollection;