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