001/*
002 * Copyright (c) 2011-2017 Nexmo Inc
003 *
004 * Permission is hereby granted, free of charge, to any person obtaining a copy
005 * of this software and associated documentation files (the "Software"), to deal
006 * in the Software without restriction, including without limitation the rights
007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008 * copies of the Software, and to permit persons to whom the Software is
009 * furnished to do so, subject to the following conditions:
010 *
011 * The above copyright notice and this permission notice shall be included in
012 * all copies or substantial portions of the Software.
013 *
014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
020 * THE SOFTWARE.
021 */
022package com.nexmo.client.application;
023
024import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
025import com.fasterxml.jackson.annotation.JsonInclude;
026import com.fasterxml.jackson.annotation.JsonProperty;
027import com.fasterxml.jackson.core.JsonProcessingException;
028import com.fasterxml.jackson.databind.ObjectMapper;
029import com.nexmo.client.NexmoUnexpectedException;
030import com.nexmo.client.application.capabilities.*;
031
032import java.io.IOException;
033
034@JsonIgnoreProperties(ignoreUnknown = true)
035@JsonInclude(JsonInclude.Include.NON_NULL)
036public class Application {
037    private String id;
038    private String name;
039    private Keys keys;
040    private Capabilities capabilities;
041
042    private Application() {
043
044    }
045
046    private Application(Builder builder) {
047        this.id = builder.id;
048        this.name = builder.name;
049        this.keys = builder.keys;
050        this.capabilities = builder.capabilities;
051    }
052
053    public String getId() {
054        return id;
055    }
056
057    public String getName() {
058        return name;
059    }
060
061    public Keys getKeys() {
062        return keys;
063    }
064
065    public Capabilities getCapabilities() {
066        return capabilities;
067    }
068
069    public String toJson() {
070        try {
071            return new ObjectMapper().writeValueAsString(this);
072        } catch (JsonProcessingException jpe) {
073            throw new NexmoUnexpectedException("Failed to produce json from Application object.", jpe);
074        }
075    }
076
077    /**
078     * @return A new Builder to start building.
079     */
080    public static Builder builder() {
081        return new Builder();
082    }
083
084    /**
085     * Copy an application to a new builder to modify into a new application object.
086     *
087     * @param application An existing application to modify.
088     *
089     * @return A new Builder to start building.
090     */
091    public static Builder builder(Application application) {
092        return new Builder(application);
093    }
094
095    public static Application fromJson(String json) {
096        try {
097            return new ObjectMapper().readValue(json, Application.class);
098        } catch (IOException e) {
099            throw new NexmoUnexpectedException("Failed to produce Application from json.", e);
100        }
101    }
102
103    public static class Builder {
104        private String id;
105        private String name;
106        private Keys keys;
107        private Capabilities capabilities;
108
109        public Builder() {
110
111        }
112
113        public Builder(Application application) {
114            this.id = application.id;
115            this.name = application.name;
116            this.keys = application.keys;
117            this.capabilities = application.capabilities;
118        }
119
120        /**
121         * @param name The name of the application.
122         *
123         * @return The {@link Builder} to keep building.
124         */
125        public Builder name(String name) {
126            this.name = name;
127            return this;
128        }
129
130        /**
131         * @param publicKey The public key for use with the application.
132         *
133         * @return The {@link Builder} to keep building.
134         */
135        public Builder publicKey(String publicKey) {
136            this.keys = new Keys();
137            this.keys.publicKey = publicKey;
138            return this;
139        }
140
141        /**
142         * Add a capability for the application. Each capability can only be used one time. Adding a capability of a
143         * duplicate type will overwrite the previous capability of that type.
144         *
145         * @param capability The capability to add to it.
146         *
147         * @return The {@link Builder} to keep building.
148         */
149        public Builder addCapability(Capability capability) {
150            if (this.capabilities == null) {
151                this.capabilities = new Capabilities();
152            }
153
154            this.capabilities.setCapability(capability);
155
156            return this;
157        }
158
159        /**
160         * Remove a capability from the application.
161         *
162         * @param type The type of capability to remove.
163         *
164         * @return The {@link Builder} to keep building.
165         */
166        public Builder removeCapability(Capability.Type type) {
167            if (this.capabilities == null) {
168                this.capabilities = new Capabilities();
169            }
170
171            this.capabilities.setCapability(type, null);
172            this.capabilities = shouldBeDeleted(this.capabilities) ? null : this.capabilities;
173            return this;
174        }
175
176        /**
177         * @return A new Application containing the configured properties.
178         */
179        public Application build() {
180            return new Application(this);
181        }
182
183        private boolean shouldBeDeleted(Capabilities capabilities) {
184            return (capabilities.voice == null
185                    && capabilities.rtc == null
186                    && capabilities.messages == null
187                    && capabilities.vbc == null);
188        }
189    }
190
191    @JsonIgnoreProperties(ignoreUnknown = true)
192    @JsonInclude(JsonInclude.Include.NON_NULL)
193    public static class Keys {
194        @JsonProperty("public_key")
195        private String publicKey;
196        @JsonProperty("private_key")
197        private String privateKey;
198
199        public String getPublicKey() {
200            return publicKey;
201        }
202
203        public String getPrivateKey() {
204            return privateKey;
205        }
206    }
207
208    @JsonIgnoreProperties(ignoreUnknown = true)
209    @JsonInclude(JsonInclude.Include.NON_NULL)
210    public static class Capabilities {
211        private Voice voice;
212        private Messages messages;
213        private Rtc rtc;
214        private Vbc vbc;
215
216        public Voice getVoice() {
217            return voice;
218        }
219
220        public Messages getMessages() {
221            return messages;
222        }
223
224        public Rtc getRtc() {
225            return rtc;
226        }
227
228        public Vbc getVbc() {
229            return vbc;
230        }
231
232        private void setCapability(Capability.Type type, Capability capability) {
233            switch (type) {
234                case VOICE:
235                    this.voice = (Voice) capability;
236                    break;
237                case MESSAGES:
238                    this.messages = (Messages) capability;
239                    break;
240                case RTC:
241                    this.rtc = (Rtc) capability;
242                    break;
243                case VBC:
244                    this.vbc = (Vbc) capability;
245                    break;
246            }
247        }
248
249        private void setCapability(Capability capability) {
250            setCapability(capability.getType(), capability);
251        }
252    }
253}