001/**
002 *
003 * Copyright 2003-2005 Jive Software.
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smackx.jingleold.packet;
018
019import java.util.ArrayList;
020import java.util.Collections;
021import java.util.Iterator;
022import java.util.List;
023
024import org.jivesoftware.smack.packet.ExtensionElement;
025
026import org.jivesoftware.smackx.jingleold.media.PayloadType;
027
028/**
029 * Jingle content description.
030 *
031 * @author Alvaro Saurin
032 */
033public abstract class JingleContentDescription implements ExtensionElement {
034
035    // static
036
037    public static final String NODENAME = "description";
038
039    // non-static
040
041    private final List<JinglePayloadType> payloads = new ArrayList<>();
042
043    /**
044     * Creates a content description..
045     */
046    public JingleContentDescription() {
047        super();
048    }
049
050    /**
051     * Returns the XML element name of the element.
052     *
053     * @return the XML element name of the element.
054     */
055    @Override
056    public String getElementName() {
057        return NODENAME;
058    }
059
060    /**
061     * Return the namespace.
062     *
063     * @return The namespace
064     */
065    @Override
066    public abstract String getNamespace();
067
068    /**
069     * Adds a audio payload type to the packet.
070     *
071     * @param pt the audio payload type to add.
072     */
073    public void addJinglePayloadType(final JinglePayloadType pt) {
074        synchronized (payloads) {
075            payloads.add(pt);
076        }
077    }
078
079    /**
080     * Adds a list of payloads to the packet.
081     *
082     * @param pts the payloads to add.
083     */
084    public void addAudioPayloadTypes(final List<PayloadType.Audio> pts) {
085        synchronized (payloads) {
086            Iterator<PayloadType.Audio> ptIter = pts.iterator();
087            while (ptIter.hasNext()) {
088                PayloadType.Audio pt = ptIter.next();
089                addJinglePayloadType(new JinglePayloadType.Audio(pt));
090            }
091        }
092    }
093
094    /**
095     * Returns an Iterator for the audio payloads in the packet.
096     *
097     * @return an Iterator for the audio payloads in the packet.
098     */
099    public Iterator<JinglePayloadType> getJinglePayloadTypes() {
100        return Collections.unmodifiableList(getJinglePayloadTypesList()).iterator();
101    }
102
103    /**
104     * Returns a list for the audio payloads in the packet.
105     *
106     * @return a list for the audio payloads in the packet.
107     */
108    public ArrayList<JinglePayloadType> getJinglePayloadTypesList() {
109        synchronized (payloads) {
110            return new ArrayList<>(payloads);
111        }
112    }
113
114    /**
115     * Return the list of Payload types contained in the description.
116     *
117     * @return a list of PayloadType.Audio
118     */
119    public ArrayList<PayloadType.Audio> getAudioPayloadTypesList() {
120        ArrayList<PayloadType.Audio> result = new ArrayList<>();
121        Iterator<JinglePayloadType> jinglePtsIter = getJinglePayloadTypes();
122
123        while (jinglePtsIter.hasNext()) {
124            JinglePayloadType jpt = jinglePtsIter.next();
125            if (jpt instanceof JinglePayloadType.Audio) {
126                JinglePayloadType.Audio jpta = (JinglePayloadType.Audio) jpt;
127                result.add((PayloadType.Audio) jpta.getPayloadType());
128            }
129        }
130
131        return result;
132    }
133
134    /**
135     * Returns a count of the audio payloads in the Jingle packet.
136     *
137     * @return the number of audio payloads in the Jingle packet.
138     */
139    public int getJinglePayloadTypesCount() {
140        synchronized (payloads) {
141            return payloads.size();
142        }
143    }
144
145    /**
146     * Convert a Jingle description to XML.
147     *
148     * @return a string with the XML representation
149     */
150    @Override
151    public String toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
152        StringBuilder buf = new StringBuilder();
153
154        synchronized (payloads) {
155            if (payloads.size() > 0) {
156                buf.append('<').append(getElementName());
157                buf.append(" xmlns=\"").append(getNamespace()).append("\" >");
158
159                Iterator<JinglePayloadType> pt = payloads.listIterator();
160                while (pt.hasNext()) {
161                    JinglePayloadType pte = pt.next();
162                    buf.append(pte.toXML());
163                }
164                buf.append("</").append(getElementName()).append('>');
165            }
166        }
167
168        return buf.toString();
169    }
170
171    /**
172     * Jingle audio description.
173     */
174    public static class Audio extends JingleContentDescription {
175
176        public static final String NAMESPACE = "urn:xmpp:tmp:jingle:apps:rtp";
177
178        public Audio() {
179            super();
180        }
181
182        /**
183         * Utility constructor, with a JinglePayloadType.
184         *
185         * @param pt the payload type.
186         */
187        public Audio(final JinglePayloadType pt) {
188            super();
189            addJinglePayloadType(pt);
190        }
191
192        @Override
193        public String getNamespace() {
194            return NAMESPACE;
195        }
196    }
197
198    /**
199     * A payload type, contained in a descriptor.
200     *
201     * @author Alvaro Saurin
202     */
203    public static class JinglePayloadType {
204
205        public static final String NODENAME = "payload-type";
206
207        private PayloadType payload;
208
209        /**
210         * Create a payload type.
211         *
212         * @param payload the payload
213         */
214        public JinglePayloadType(final PayloadType payload) {
215            super();
216            this.payload = payload;
217        }
218
219        /**
220         * Create an empty payload type.
221         */
222        public JinglePayloadType() {
223            this(null);
224        }
225
226        /**
227         * Returns the XML element name of the element.
228         *
229         * @return the XML element name of the element.
230         */
231        public static String getElementName() {
232            return NODENAME;
233        }
234
235        /**
236         * Get the payload represented.
237         *
238         * @return the payload
239         */
240        public PayloadType getPayloadType() {
241            return payload;
242        }
243
244        /**
245         * Set the payload represented.
246         *
247         * @param payload the payload to set
248         */
249        public void setPayload(final PayloadType payload) {
250            this.payload = payload;
251        }
252
253        protected String getChildAttributes() {
254            return null;
255        }
256
257        public String toXML() {
258            StringBuilder buf = new StringBuilder();
259
260            if (payload != null) {
261                buf.append('<').append(getElementName()).append(' ');
262
263                // We covert here the payload type to XML
264                if (payload.getId() != PayloadType.INVALID_PT) {
265                    buf.append(" id=\"").append(payload.getId()).append('"');
266                }
267                if (payload.getName() != null) {
268                    buf.append(" name=\"").append(payload.getName()).append('"');
269                }
270                if (payload.getChannels() != 0) {
271                    buf.append(" channels=\"").append(payload.getChannels()).append('"');
272                }
273                if (getChildAttributes() != null) {
274                    buf.append(getChildAttributes());
275                }
276                buf.append("/>");
277            }
278            return buf.toString();
279        }
280
281        /**
282         * Audio payload type element.
283         */
284        public static class Audio extends JinglePayloadType {
285            public Audio(final PayloadType.Audio audio) {
286                super(audio);
287            }
288
289            @Override
290            protected String getChildAttributes() {
291                StringBuilder buf = new StringBuilder();
292                PayloadType pt = getPayloadType();
293                if (pt instanceof PayloadType.Audio) {
294                    PayloadType.Audio pta = (PayloadType.Audio) pt;
295
296                    buf.append(" clockrate=\"").append(pta.getClockRate()).append("\" ");
297                }
298                return buf.toString();
299            }
300        }
301    }
302}