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(String 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        public Audio(final JinglePayloadType pt) {
186            super();
187            addJinglePayloadType(pt);
188        }
189
190        @Override
191        public String getNamespace() {
192            return NAMESPACE;
193        }
194    }
195
196    /**
197     * A payload type, contained in a descriptor.
198     *
199     * @author Alvaro Saurin
200     */
201    public static class JinglePayloadType {
202
203        public static final String NODENAME = "payload-type";
204
205        private PayloadType payload;
206
207        /**
208         * Create a payload type.
209         *
210         * @param payload the payload
211         */
212        public JinglePayloadType(final PayloadType payload) {
213            super();
214            this.payload = payload;
215        }
216
217        /**
218         * Create an empty payload type.
219         */
220        public JinglePayloadType() {
221            this(null);
222        }
223
224        /**
225         * Returns the XML element name of the element.
226         *
227         * @return the XML element name of the element.
228         */
229        public static String getElementName() {
230            return NODENAME;
231        }
232
233        /**
234         * Get the payload represented.
235         *
236         * @return the payload
237         */
238        public PayloadType getPayloadType() {
239            return payload;
240        }
241
242        /**
243         * Set the payload represented.
244         *
245         * @param payload the payload to set
246         */
247        public void setPayload(final PayloadType payload) {
248            this.payload = payload;
249        }
250
251        protected String getChildAttributes() {
252            return null;
253        }
254
255        public String toXML() {
256            StringBuilder buf = new StringBuilder();
257
258            if (payload != null) {
259                buf.append('<').append(getElementName()).append(' ');
260
261                // We covert here the payload type to XML
262                if (payload.getId() != PayloadType.INVALID_PT) {
263                    buf.append(" id=\"").append(payload.getId()).append('"');
264                }
265                if (payload.getName() != null) {
266                    buf.append(" name=\"").append(payload.getName()).append('"');
267                }
268                if (payload.getChannels() != 0) {
269                    buf.append(" channels=\"").append(payload.getChannels()).append('"');
270                }
271                if (getChildAttributes() != null) {
272                    buf.append(getChildAttributes());
273                }
274                buf.append("/>");
275            }
276            return buf.toString();
277        }
278
279        /**
280         * Audio payload type element.
281         */
282        public static class Audio extends JinglePayloadType {
283            public Audio(final PayloadType.Audio audio) {
284                super(audio);
285            }
286
287            @Override
288            protected String getChildAttributes() {
289                StringBuilder buf = new StringBuilder();
290                PayloadType pt = getPayloadType();
291                if (pt instanceof PayloadType.Audio) {
292                    PayloadType.Audio pta = (PayloadType.Audio) pt;
293
294                    buf.append(" clockrate=\"").append(pta.getClockRate()).append("\" ");
295                }
296                return buf.toString();
297            }
298        }
299    }
300}