1 /*
2 * jSDP: A Java implementation of SDP protocol Copyright (C) 2007 Claudio Di
3 * Vita
4 */
5 package net.sourceforge.jsdp;
6
7 import java.util.Vector;
8
9 import net.sourceforge.jsdp.util.TypedTime;
10
11 /**
12 * A <tt>RepeatTime</tt> represents a <b>r=<i><field value></i></b>
13 * field contained in a SDP message. A repeat time field specify repeat times
14 * for a session: his consists of a <i>repeat interval</i>, an <i>active
15 * duration</i> and a list of offsets relative to the
16 * {@link Time#getStartTime()} start time.
17 *
18 * @see Time
19 *
20 * @since 0.1.0
21 *
22 * @version 1.0
23 *
24 * @author <a href="mailto:cdivita@users.sourceforge.net">Claudio Di Vita</a>
25 */
26 public class RepeatTime implements Field {
27
28 /** The class Stream Unique Identifier, SUID */
29 private static final long serialVersionUID = -7772961172651467572L;
30
31 /** The repeat interval */
32 protected long repeatInterval;
33
34 /** The active duraction */
35 protected long activeDuration;
36
37 /** The list of offset relative to the <b>t</b> field start time */
38 protected Vector offsets;
39
40 /** Indicates if the field will be output as a typed time or a number */
41 protected boolean isTyped;
42
43 /**
44 * Creates a new <tt>RepeatTime</tt>.
45 */
46 protected RepeatTime() {
47
48 super();
49 }
50
51 /**
52 * Creates a new <tt>RepeatTime</tt>.
53 *
54 * @param repeatInterval the repeat interval
55 *
56 * @param activeDuration the active duration
57 *
58 * @param offset the offset
59 *
60 * @throws SDPException if the parameters are not valid
61 */
62 public RepeatTime(final long repeatInterval, final long activeDuration, final long offset) throws SDPException {
63
64 super();
65
66 this.isTyped = true;
67
68 setActiveDuration(activeDuration);
69 setRepeatInterval(repeatInterval);
70
71 this.offsets = new Vector(3);
72 addOffset(offset);
73 }
74
75 /**
76 * Creates a new <tt>RepeatTime</tt>.
77 *
78 * @param repeatInterval the repeat interval
79 *
80 * @param activeDuration the active duration
81 *
82 * @param offsets the offsets
83 *
84 * @throws SDPException if the parameters are not valid
85 */
86 public RepeatTime(final long repeatInterval, final long activeDuration, final long[] offsets) throws SDPException {
87
88 super();
89
90 this.isTyped = true;
91
92 setRepeatInterval(repeatInterval);
93 setActiveDuration(activeDuration);
94
95 this.offsets = new Vector(offsets.length);
96 for (int i = 0; i < offsets.length; i++) {
97 addOffset(offsets[i]);
98 }
99 }
100
101 /**
102 * Parse an input string and constructs the equivalent repeat time field.
103 *
104 * @param field the string to parse
105 *
106 * @return a new <tt>RepeatTime</tt> instance
107 *
108 * @throws SDPParseException if an error occurs while parsing
109 */
110 public static RepeatTime parse(final String field) throws SDPParseException {
111
112 if (!field.startsWith("r=")) {
113 throw new SDPParseException("The string \"" + field + "\" isn't a repeat time field");
114 }
115
116 RepeatTime r = null;
117
118 long repeatInterval;
119 long activeDuration;
120 long[] offsets;
121
122 String[] values = field.substring(2).split(" ");
123
124 try {
125 switch (values.length) {
126 case 0:
127 case 1:
128 case 2:
129 throw new SDPParseException("The string \"" + field + "\" isn't a valid repeat time field");
130 default:
131 /* Get the repeat interval */
132 repeatInterval = TypedTime.getTime(values[0]);
133
134 /* Get the active duraction */
135 activeDuration = TypedTime.getTime(values[1]);
136
137 /* Get the offsets */
138 offsets = new long[values.length - 2];
139 for (int i = 0; i < offsets.length; i++) {
140 offsets[i] = TypedTime.getTime(values[i + 2]);
141 }
142
143 /* Create the field */
144 r = new RepeatTime(repeatInterval, activeDuration, offsets);
145 }
146 }
147 catch (SDPException parseException) {
148 throw new SDPParseException("The string \"" + field + "\" isn't a valid repeat time field", parseException);
149 }
150
151 return r;
152 }
153
154 /**
155 * Adds an offset to the field.
156 *
157 * @param offset the offset value
158 *
159 * @throws SDPException if the offset value is negative
160 */
161 public void addOffset(final long offset) throws SDPException {
162
163 if (offset >= 0) {
164 offsets.add(new Long(offset));
165 }
166 else {
167 throw new SDPException("Offsets must be >= 0");
168 }
169 }
170
171 /**
172 * Returns a clone of this field.
173 *
174 * @return a clone of this field
175 */
176 public Object clone() {
177
178 RepeatTime field = new RepeatTime();
179 field.isTyped = this.isTyped;
180 field.activeDuration = this.activeDuration;
181 field.repeatInterval = this.repeatInterval;
182 field.offsets = (Vector) this.offsets.clone();
183
184 return field;
185 }
186
187 /**
188 * Returns the active duration in seconds
189 *
190 * @return the active duration
191 */
192 public long getActiveDuration() {
193
194 return activeDuration;
195 }
196
197 /**
198 * Returns the list of offsets. These are relative to the start time given
199 * in the {@link Time} field with which this <tt>RepeatTime</tt> is
200 * associated.
201 *
202 * @return an array of repeat time offsets
203 */
204 public long[] getOffsets() {
205
206 long[] values = new long[offsets.size()];
207 for (int i = 0; i < values.length; i++) {
208 Long offset = (Long) offsets.get(i);
209 values[i] = offset.longValue();
210 }
211
212 return values;
213 }
214
215 /**
216 * Returns the repeat interval.
217 *
218 * @return the repeat interval in seconds
219 */
220 public long getRepeatInterval() {
221
222 return repeatInterval;
223 }
224
225 /**
226 * Returns the type character for the field.
227 *
228 * @return the field type character: <b>r</b>
229 */
230 public char getType() {
231
232 return Field.REPEAT_TIME_FIELD;
233 }
234
235 /**
236 * Returns whether the field will be output as a typed time or a number.
237 *
238 * <p>
239 * Typed time is formatted as an number followed by a unit character: the
240 * unit indicates an appropriate multiplier for the number. The following
241 * unit types are allowed:
242 * </p>
243 * <ul>
244 * <li><tt><b>d</b></tt> - days (86400 seconds)</li>
245 * <li><tt><b>h</b></tt> - hours (3600 seconds)</li>
246 * <li><tt><b>m</b></tt> - minutes (60 seconds)</li>
247 * <li><tt><b>s</b></tt> - seconds (1 second)</li>
248 * </ul>
249 *
250 * @return <tt>true</tt> if the field will be output as a typed time,
251 * <tt>false</tt> if as a number
252 */
253 public boolean isTypedTime() {
254
255 return isTyped;
256 }
257
258 /**
259 * Sets the active duration.
260 *
261 * @param activeDuration the active duration in seconds
262 *
263 * @throws SDPException if the active duration is negative
264 */
265 public void setActiveDuration(final long activeDuration) throws SDPException {
266
267 if (activeDuration < 0) {
268 throw new SDPException("The active duration cannot be negative");
269 }
270
271 this.activeDuration = activeDuration;
272
273 }
274
275 /**
276 * Set the list of offsets. These are relative to the start time given in
277 * the {@link Time} field with which this <tt>RepeatTime</tt> is
278 * associated.
279 *
280 * @param offsets an array of repeat time offsets
281 *
282 * @throws SDPException if one or more offset is negative
283 */
284 public void setOffset(final long[] offsets) throws SDPException {
285
286 Vector temp = new Vector(offsets.length);
287 for (int i = 0; i < offsets.length; i++) {
288 if (offsets[i] >= 0) {
289 temp.add(new Long(offsets[i]));
290 }
291 else {
292 throw new SDPException("Offsets must be >= 0");
293 }
294 }
295 // this.offsets = null;
296 // this.offsets = (Vector)temp.clone();
297 this.offsets = temp;
298 }
299
300 /**
301 * Sets the repeat interval.
302 *
303 * @param repeatInterval the repeat interval in seconds
304 *
305 * @throws SDPException if repeatInterval is negative
306 */
307 public void setRepeatInterval(final long repeatInterval) throws SDPException {
308
309 if (repeatInterval < 0) {
310 throw new SDPException("The repeat interval cannot be negative");
311 }
312
313 this.repeatInterval = repeatInterval;
314 }
315
316 /**
317 * Sets whether the field will be output as a typed time or a number. Typed
318 * time is formatted as an number followed by a unit character: the unit
319 * indicates an appropriate multiplier for the number. The following unit
320 * types are allowed:
321 * <ul>
322 * <li><tt><b>d</b></tt> - days (86400 seconds)</li>
323 * <li><tt><b>h</b></tt> - hours (3600 seconds)</li>
324 * <li><tt><b>m</b></tt> - minutes (60 seconds)</li>
325 * <li><tt><b>s</b></tt> - seconds (1 second)</li>
326 * </ul>
327 */
328 public void setTypedTime(final boolean typedTime) {
329
330 this.isTyped = typedTime;
331 }
332
333 /**
334 * Returns a string representation of the field. The representation has the
335 * form: <b>r=<i><value></i></b>
336 *
337 * @return the string representation of the field
338 */
339 public String toString() {
340
341 StringBuffer result;
342
343 result = new StringBuffer(getType() + "=");
344
345 result.append(repeatInterval + " ");
346 if (this.isTyped) {
347 result.append(TypedTime.toString(activeDuration));
348 for (int i = 0; i < offsets.size(); i++) {
349 Long offset = (Long) offsets.get(i);
350 result.append(" " + TypedTime.toString(offset.longValue()));
351 }
352 }
353 else {
354 result.append(activeDuration);
355 for (int i = 0; i < offsets.size(); i++) {
356 result.append(" " + offsets.get(i));
357 }
358 }
359
360 return result.toString();
361 }
362 }