001/* 002 * Copyright 2024 Vonage 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.vonage.client.voice.ncco; 017 018import com.fasterxml.jackson.annotation.JsonProperty; 019import com.vonage.client.JsonableBaseObject; 020import java.util.*; 021 022/** 023 * An NCCO input action which allows for the collection of digits and automatic speech recognition from a person. 024 */ 025public class InputAction extends JsonableBaseObject implements Action { 026 private static final String ACTION = "input"; 027 028 @JsonProperty(required = true) 029 private Collection<String> type; 030 private DtmfSettings dtmf; 031 private Collection<String> eventUrl; 032 private SpeechSettings speech; 033 private EventMethod eventMethod; 034 private InputMode mode; 035 036 InputAction() {} 037 038 private InputAction(Builder builder) { 039 eventUrl = builder.eventUrl; 040 eventMethod = builder.eventMethod; 041 speech = builder.speech; 042 mode = builder.mode; 043 if ((type = builder.type).isEmpty()) { 044 throw new IllegalStateException("At least one input type must be specified."); 045 } 046 if ((dtmf = builder.dtmf) != null && mode == InputMode.ASYNCHRONOUS) { 047 throw new IllegalStateException("DTMF settings cannot be used with asynchronous mode."); 048 } 049 } 050 051 @Override 052 public String getAction() { 053 return ACTION; 054 } 055 056 @JsonProperty("type") 057 public Collection<String> getType() { 058 return type; 059 } 060 061 @JsonProperty("dtmf") 062 public DtmfSettings getDtmf() { 063 return dtmf; 064 } 065 066 @JsonProperty("eventUrl") 067 public Collection<String> getEventUrl() { 068 return eventUrl; 069 } 070 071 @JsonProperty("eventMethod") 072 public EventMethod getEventMethod() { 073 return eventMethod; 074 } 075 076 @JsonProperty("speech") 077 public SpeechSettings getSpeech() { 078 return speech; 079 } 080 081 /** 082 * How the input should be processed. If not set, the default is {@linkplain InputMode#SYNCHRONOUS}. 083 * 084 * @return The mode as an enum, or {@code null} if unspecified. 085 * @since 8.12.0 086 */ 087 @JsonProperty("mode") 088 public InputMode getMode() { 089 return mode; 090 } 091 092 /** 093 * Entrypoint for constructing an instance of this class. 094 * 095 * @return A new Builder. 096 */ 097 public static Builder builder() { 098 return new Builder(); 099 } 100 101 /** 102 * Builder for specifying the properties of an InputAction. 103 */ 104 public static class Builder { 105 private final Collection<String> type = new LinkedHashSet<>(2, 1f); 106 private DtmfSettings dtmf; 107 private Collection<String> eventUrl; 108 private EventMethod eventMethod; 109 private SpeechSettings speech; 110 private InputMode mode; 111 112 private Builder() {} 113 114 /** 115 * Enables DTMF with the default settings. 116 * 117 * @return This builder to keep building the input action. 118 * @since 8.12.0 119 */ 120 public Builder dtmf() { 121 dtmf(null); 122 type.add("dtmf"); 123 return this; 124 } 125 126 /** 127 * Enable DTMF input with the provided settings. Note that if you override any of 128 * the defaults, you cannot set {@linkplain #mode(InputMode)} to {@linkplain InputMode#ASYNCHRONOUS}. 129 * 130 * @param dtmf The DTMF settings object. 131 * @return This builder to keep building the input action. 132 * @since 6.0.0 133 */ 134 public Builder dtmf(DtmfSettings dtmf) { 135 if ((this.dtmf = dtmf) != null) { 136 type.add("dtmf"); 137 } 138 else { 139 type.remove("dtmf"); 140 } 141 return this; 142 } 143 144 /** 145 * Automatic Speech Recognition (ASR) settings to enable speech input. 146 * Required if {@linkplain #dtmf(DtmfSettings)} is not provided. 147 * 148 * @param speech The speech settings object. 149 * @return This builder to keep building the input action. 150 * @since 6.0.0 151 */ 152 public Builder speech(SpeechSettings speech) { 153 if ((this.speech = speech) != null) { 154 type.add("speech"); 155 } 156 else { 157 type.remove("speech"); 158 } 159 return this; 160 } 161 162 /** 163 * Vonage sends the digits pressed by the callee to this URL after timeOut pause inactivity or when 164 * {@code #} is pressed. 165 * 166 * @param eventUrl The URL wrapped in a singleton collection to send the event metadata to. 167 * 168 * @return This builder to keep building the input action. 169 * @deprecated This will be removed in a future release. Use {@link #eventUrl(String)} instead. 170 */ 171 @Deprecated 172 public Builder eventUrl(Collection<String> eventUrl) { 173 this.eventUrl = eventUrl; 174 return this; 175 } 176 177 /** 178 * Vonage sends the digits pressed by the callee to this URL after timeOut pause inactivity or when 179 * {@code #} is pressed. 180 * 181 * @param eventUrl The URL to send the event metadata to. 182 * 183 * @return This builder to keep building the input action. 184 * @deprecated This will be removed in a future release. Use {@link #eventUrl(String)} instead. 185 */ 186 @Deprecated 187 public Builder eventUrl(String... eventUrl) { 188 return eventUrl(Arrays.asList(eventUrl)); 189 } 190 191 /** 192 * Vonage sends the digits pressed by the callee to this URL after timeOut pause inactivity or when 193 * {@code #} is pressed. 194 * 195 * @param eventUrl The URL to send the event metadata to. 196 * 197 * @return This builder to keep building the input action. 198 * 199 * @since 8.12.0 200 */ 201 public Builder eventUrl(String eventUrl) { 202 return eventUrl(Collections.singletonList(eventUrl)); 203 } 204 205 /** 206 * The HTTP method used to send event information to event_url The default value is POST. 207 * 208 * @param eventMethod The HTTP method to use for the event as an enum. 209 * 210 * @return This builder to keep building the input action. 211 */ 212 public Builder eventMethod(EventMethod eventMethod) { 213 this.eventMethod = eventMethod; 214 return this; 215 } 216 217 /** 218 * How the input should be processed. If not set, the default is {@linkplain InputMode#SYNCHRONOUS}. 219 * If set to {@linkplain InputMode#ASYNCHRONOUS}, use {@link #dtmf()} instead of {@link #dtmf(DtmfSettings)}. 220 * 221 * @param mode The DTMF processing mode as an enum. 222 * @return This builder to keep building the input action. 223 * @since 8.12.0 224 */ 225 public Builder mode(InputMode mode) { 226 this.mode = mode; 227 return this; 228 } 229 230 /** 231 * Sets the acceptable input types. From v8.12.0 onwards, you should not call this method manually; 232 * instead, use {@link #dtmf()} and / or {@link #speech(SpeechSettings)}. This method will be removed 233 * in a future release. 234 * 235 * @param type Acceptable input types as a collection. Valid values are ["dtmf"] for DTMF input only, 236 * ["speech"] for ASR only, or ["dtmf", "speech"] for both. 237 * 238 * @return This builder to keep building the input action. 239 * 240 * @deprecated Use {@link #dtmf(DtmfSettings)} and {@link #speech(SpeechSettings)} instead. 241 * The type will be set automatically based on the provided settings. 242 */ 243 @Deprecated 244 public Builder type(Collection<String> type) { 245 this.type.clear(); 246 if (type != null) { 247 this.type.addAll(type); 248 } 249 return this; 250 } 251 252 /** 253 * Builds the InputAction. 254 * 255 * @return A new InputAction object from the stored builder options. 256 */ 257 public InputAction build() { 258 return new InputAction(this); 259 } 260 } 261}