001package com.plivo.api.xml;
002
003import com.plivo.api.exceptions.PlivoXmlException;
004import com.plivo.api.util.Utils;
005import java.util.ArrayList;
006import java.util.Arrays;
007import java.util.List;
008import javax.xml.bind.annotation.XmlAttribute;
009import javax.xml.bind.annotation.XmlElement;
010import javax.xml.bind.annotation.XmlElements;
011import javax.xml.bind.annotation.XmlMixed;
012import javax.xml.bind.annotation.XmlRootElement;
013import javax.xml.bind.annotation.XmlSeeAlso;
014import javax.xml.bind.annotation.XmlValue;
015
016
017@XmlRootElement(name = "Speak")
018@XmlSeeAlso({Lang.class,
019      Emphasis.class,
020      Break.class,
021      SayAs.class,
022      Sub.class,
023      S.class,
024      W.class,
025      P.class,
026      Phoneme.class,
027      Prosody.class,
028      })
029public class Speak extends PlivoXml implements ResponseNestable, PreAnswerNestable, GetDigitsNestable, GetInputNestable {
030
031  //public String content;
032  @XmlMixed
033  private List<Object> mixedContent = new ArrayList<Object>();
034
035  @XmlAttribute
036  private String voice;
037
038  @XmlAttribute
039  private String language;
040
041  @XmlAttribute
042  private Integer loop;
043
044  private static int MAX_CONTENT_LENGTH = 3000;
045
046  public Speak() {
047
048  }
049
050  public Speak(String content) {
051    this.mixedContent.add(content);
052  }
053
054  public Speak(String content, String voice, String language, Integer loop) throws PlivoXmlException {
055
056    this.mixedContent.add(content);
057    this.voice = voice;
058    this.language = language;
059    this.loop = loop;
060
061    if (voice == null || voice.trim().isEmpty()){
062        this.voice = "WOMAN";
063        return;
064    }
065    if (voice.equalsIgnoreCase("MAN") || voice.equalsIgnoreCase("WOMAN")) {
066        return;
067    }
068
069    this.voice = transformVoiceString(voice);
070    Utils.validateLanguageVoice(language, voice);
071  }
072
073  public String getVoice() {
074    return voice;
075  }
076
077  public String getLanguage() {
078    return language;
079  }
080
081  public Integer getLoop() {
082    return loop;
083  }
084
085  private void checkIsSSMLSupported() throws PlivoXmlException {
086        if (this.voice == null || this.voice.trim().isEmpty() ||
087                        this.voice.equalsIgnoreCase("MAN") || this.voice.equalsIgnoreCase("WOMAN")) { 
088                throw new PlivoXmlException("SSML support is available only for Amazon Polly!");
089    }
090  }
091
092  private static String transformVoiceString(String voice) {
093    String[] voiceParts = voice.trim().split("\\.");
094    if (voiceParts.length == 1) {
095      return voice;
096    }
097    String voiceName = Utils.transformString(voiceParts[1]);
098    return voiceParts[0] + "." + voiceName;
099  }
100
101  public Speak addBreak(String strength, String time) throws PlivoXmlException {
102        this.checkIsSSMLSupported();
103    this.mixedContent.add(new Break(strength, time));
104    return this;
105  }
106
107  public Speak addEmphasis(String content, String level) throws PlivoXmlException {
108        this.checkIsSSMLSupported();
109    this.mixedContent.add(new Emphasis(content, level));
110    return this;
111  }
112
113  public Speak addLang(String content, String xmllang) throws PlivoXmlException {
114        this.checkIsSSMLSupported();
115    this.mixedContent.add(new Lang(content, xmllang));
116    return this;
117  }
118
119  public Speak addP(String content) throws PlivoXmlException {
120        this.checkIsSSMLSupported();
121    this.mixedContent.add(new P(content));
122    return this;
123  }
124
125  public Speak addPhoneme(String content, String alphabet, String ph) throws PlivoXmlException {
126        this.checkIsSSMLSupported();
127    this.mixedContent.add(new Phoneme(content, alphabet, ph));
128    return this;
129  }
130
131  public Speak addProsody(String content) throws PlivoXmlException {
132    this.checkIsSSMLSupported();
133    this.mixedContent.add(new Prosody(content));
134    return this;
135  }
136
137  public Speak addProsody(String content, String volume, String rate, String pitch) throws PlivoXmlException {
138    this.checkIsSSMLSupported();
139    this.mixedContent.add(new Prosody(content, volume, rate, pitch));
140    return this;
141  }
142
143  public Speak addS(String content) throws PlivoXmlException {
144        this.checkIsSSMLSupported();
145    this.mixedContent.add(new S(content));
146    return this;
147  }
148
149  public Speak addSayAs(String content, String interpretAs) throws PlivoXmlException {
150        this.checkIsSSMLSupported();
151    this.mixedContent.add(new SayAs(content, interpretAs));
152    return this;
153  }
154
155  public Speak addSayAs(String content, String interpretAs, String format) throws PlivoXmlException {
156    this.checkIsSSMLSupported();
157    this.mixedContent.add(new SayAs(content, interpretAs, format));
158    return this;
159  }
160
161  public Speak addSub(String content, String alias) throws PlivoXmlException {
162        this.checkIsSSMLSupported();
163    this.mixedContent.add(new Sub(content, alias));
164    return this;
165  }
166
167  public Speak addW(String content, String role) throws PlivoXmlException {
168        this.checkIsSSMLSupported();
169    this.mixedContent.add(new W(content, role));
170    return this;
171  }
172
173  public Speak continueSpeak(String content) throws PlivoXmlException {
174    this.mixedContent.add(content);
175    return this;
176  }
177
178  public Speak children(Object... nestables) throws PlivoXmlException {
179    for (Object obj : nestables) {
180      if (obj instanceof SpeakNestable || obj instanceof String) {
181        mixedContent.add(obj);
182      } else {
183        throw new PlivoXmlException("XML Validation Error: <" + obj.getClass().getSimpleName() + "> can not be nested in <Speak>");
184      }
185    }
186    return this;
187  }
188}