001/*
002 * Copyright (c) 2013 Nu Echo Inc. All rights reserved.
003 */
004
005package com.nuecho.rivr.voicexml.turn.output;
006
007import static com.nuecho.rivr.core.util.Assert.*;
008import static com.nuecho.rivr.voicexml.rendering.voicexml.VoiceXmlDomUtil.*;
009
010import java.util.*;
011
012import javax.json.*;
013
014import org.w3c.dom.*;
015
016import com.nuecho.rivr.core.util.*;
017import com.nuecho.rivr.voicexml.dialogue.*;
018import com.nuecho.rivr.voicexml.rendering.voicexml.*;
019import com.nuecho.rivr.voicexml.turn.output.audio.*;
020import com.nuecho.rivr.voicexml.util.json.*;
021
022/**
023 * A {@link Message} is a {@link VoiceXmlOutputTurn} that plays a sequence of
024 * {@link AudioItem}.
025 *
026 * @author Nu Echo Inc.
027 * @see AudioItem
028 * @see <a href=
029 *      "https://www.w3.org/TR/voicexml20/#dml4.1.8">https://www.w3.org/TR/voicexml20/#dml4.1.8</a>
030 */
031public class Message extends VoiceXmlOutputTurn {
032    private static final String MESSAGE_TURN_TYPE = "message";
033
034    private static final String BARGE_IN_PROPERTY = "bargeIn";
035    private static final String LANGUAGE_PROPERTY = "language";
036    private static final String AUDIO_ITEMS_PROPERTY = "audioItems";
037
038    private final List<AudioItem> mAudioItems;
039    private String mLanguage;
040    private Boolean mBargeIn;
041
042    /**
043     * @param name The name of this turn. Not empty.
044     * @param audioItems The sequence of {@link AudioItem} to play. Not empty.
045     */
046    public Message(String name, List<AudioItem> audioItems) {
047        super(name);
048        Assert.notEmpty(audioItems, "audioItems");
049        mAudioItems = new ArrayList<AudioItem>(audioItems);
050    }
051
052    /**
053     * @param name The name of this turn. Not empty.
054     * @param audioItems The sequence of {@link AudioItem} to play. Not empty.
055     */
056    public Message(String name, AudioItem... audioItems) {
057        this(name, asListChecked(audioItems));
058    }
059
060    /**
061     * @param language The language identifier (e.g. "en-US") for the message.
062     *            <code>null</code> to use the VoiceXML platform default
063     */
064    public final void setLanguage(String language) {
065        mLanguage = language;
066    }
067
068    /**
069     * @param bargeIn
070     *            <ul>
071     *            <li>{@link Boolean#TRUE} to enable barge-in</li>
072     *            <li>{@link Boolean#FALSE} to disable barge-in</li>
073     *            <li><code>null</code> to use the VoiceXML platform
074     *            default</li>
075     *            </ul>
076     */
077    public final void setBargeIn(Boolean bargeIn) {
078        mBargeIn = bargeIn;
079    }
080
081    public final List<AudioItem> getAudioItems() {
082        return Collections.unmodifiableList(mAudioItems);
083    }
084
085    public final String getLanguage() {
086        return mLanguage;
087    }
088
089    public final Boolean getBargeIn() {
090        return mBargeIn;
091    }
092
093    @Override
094    protected final String getOuputTurnType() {
095        return MESSAGE_TURN_TYPE;
096    }
097
098    @Override
099    protected void addTurnProperties(JsonObjectBuilder builder) {
100        JsonUtils.add(builder, AUDIO_ITEMS_PROPERTY, JsonUtils.toJson(mAudioItems));
101        JsonUtils.add(builder, LANGUAGE_PROPERTY, mLanguage);
102        if (mBargeIn == null) {
103            builder.addNull(BARGE_IN_PROPERTY);
104        } else {
105            builder.add(BARGE_IN_PROPERTY, mBargeIn.booleanValue());
106        }
107    }
108
109    @Override
110    protected void fillVoiceXmlDocument(Document document, Element formElement, VoiceXmlDialogueContext dialogueContext)
111            throws VoiceXmlDocumentRenderingException {
112        Element blockElement = addBlockElement(formElement);
113        createPrompt(mLanguage, blockElement, dialogueContext, mBargeIn, mAudioItems);
114        createGotoSubmit(blockElement);
115    }
116
117    /**
118     * Builder used to ease the creation of instances of {@link Message}.
119     */
120    public static class Builder {
121
122        private final String mName;
123        private final List<AudioItem> mAudioItems = new ArrayList<AudioItem>();
124        private String mLanguage;
125        private Boolean mBargeIn;
126
127        public Builder(String name) {
128            mName = name;
129        }
130
131        /**
132         * Add an audio item.
133         *
134         * @param audioItem the audio item to add
135         * @return this builder
136         * @deprecated Use {@link #addAudioItem(AudioItem)} instead
137         */
138        @Deprecated
139        public Builder addAudio(AudioItem audioItem) {
140            return addAudioItem(audioItem);
141        }
142
143        /**
144         * Add an audio item.
145         *
146         * @param audioItem the audio item to add
147         * @return this builder
148         * @since 1.0.1
149         */
150        public Builder addAudioItem(AudioItem audioItem) {
151            Assert.notNull(audioItem, "audioItem");
152            mAudioItems.add(audioItem);
153            return this;
154        }
155
156        /**
157         * Add some audio items.
158         *
159         * @param audioItems the audio items to add
160         * @return this builder
161         * @since 1.0.1
162         */
163        public Builder addAudioItems(AudioItem... audioItems) {
164            return addAudioItems(asListChecked(audioItems));
165        }
166
167        /**
168         * Add some audio items.
169         *
170         * @param audioItems the audio items to add
171         * @return this builder
172         */
173        public Builder addAudioItems(List<AudioItem> audioItems) {
174            Assert.noNullValues(audioItems, mLanguage);
175            mAudioItems.addAll(audioItems);
176            return this;
177        }
178
179        public Builder setLanguage(String language) {
180            mLanguage = language;
181            return this;
182        }
183
184        public Builder setBargein(Boolean bargeIn) {
185            mBargeIn = bargeIn;
186            return this;
187        }
188
189        /**
190         * Build the message.
191         *
192         * @return the message
193         */
194        public Message build() {
195            Message message = new Message(mName, mAudioItems);
196            message.setBargeIn(mBargeIn);
197            message.setLanguage(mLanguage);
198            return message;
199        }
200    }
201
202    @Override
203    public int hashCode() {
204        final int prime = 31;
205        int result = super.hashCode();
206        result = prime * result + ((mAudioItems == null) ? 0 : mAudioItems.hashCode());
207        result = prime * result + ((mBargeIn == null) ? 0 : mBargeIn.hashCode());
208        result = prime * result + ((mLanguage == null) ? 0 : mLanguage.hashCode());
209        return result;
210    }
211
212    @Override
213    public boolean equals(Object obj) {
214        if (this == obj) return true;
215        if (!super.equals(obj)) return false;
216        if (getClass() != obj.getClass()) return false;
217        Message other = (Message) obj;
218        if (mAudioItems == null) {
219            if (other.mAudioItems != null) return false;
220        } else if (!mAudioItems.equals(other.mAudioItems)) return false;
221        if (mBargeIn == null) {
222            if (other.mBargeIn != null) return false;
223        } else if (!mBargeIn.equals(other.mBargeIn)) return false;
224        if (mLanguage == null) {
225            if (other.mLanguage != null) return false;
226        } else if (!mLanguage.equals(other.mLanguage)) return false;
227        return true;
228    }
229
230}