~ubuntu-branches/ubuntu/quantal/freeguide/quantal

« back to all changes in this revision

Viewing changes to src/program/gui/viewer/ViewerFrameXMLTVLoader.java

  • Committer: Bazaar Package Importer
  • Author(s): Shaun Jackman
  • Date: 2006-09-30 10:14:18 UTC
  • mfrom: (1.2.3 upstream) (3.1.1 etch)
  • Revision ID: james.westby@ubuntu.com-20060930101418-pkilk36yy22nbt3r
Tags: 0.10.4-2
Update the watch file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  FreeGuide
3
 
 *
4
 
 *  Copyright (c) 2001-2004 by Andy Balaam and the FreeGuide contributors
5
 
 *
6
 
 *  Released under the GNU General Public License
7
 
 *  with ABSOLUTELY NO WARRANTY.
8
 
 *
9
 
 *  See the file COPYING for more information.
10
 
 */
11
 
package freeguide.gui.viewer;
12
 
 
13
 
import freeguide.*;
14
 
import freeguide.lib.fgspecific.*;
15
 
import freeguide.lib.general.*;
16
 
import java.io.*;
17
 
import java.net.*;
18
 
import java.text.*;
19
 
import java.util.*;
20
 
import java.util.regex.*;
21
 
import javax.xml.parsers.*;
22
 
import org.xml.sax.helpers.*;
23
 
import org.xml.sax.*;
24
 
 
25
 
/**
26
 
 *  XMLTVLoader Loads the required XMLTV files for a given date into a Vector of
27
 
 *  programmes and stores other relevant details e.g. channel details
28
 
 *
29
 
 *@author     andy
30
 
 *@created    28 June 2003
31
 
 *@version    4
32
 
 */
33
 
 
34
 
public class ViewerFrameXMLTVLoader extends DefaultHandler implements ChannelSetInterface {
35
 
 
36
 
    /**
37
 
     *  Loads the programme data from a file and stores it in a class structure
38
 
     *  ready for display on the screen.
39
 
     *
40
 
     *@param  nowDate  The date and time for which to load programmes
41
 
     */
42
 
    public void loadProgrammeData( Calendar nowDate ) {
43
 
 
44
 
        thereAreEarlyProgs = false;
45
 
        thereAreLateProgs = false;
46
 
 
47
 
        // Find out the span of time for this day (using day_start_time)
48
 
        // and alter the date if we're actually asking for a time that falls
49
 
        // on the previous date
50
 
        updateDaySpan( nowDate );
51
 
 
52
 
        setupHasDataStuff( nowDate );
53
 
 
54
 
        // Prepare the vectors that will contain the parsed data
55
 
        programmes = new Vector();
56
 
        channelIDs = new Vector();
57
 
        channelNames = new Vector();
58
 
 
59
 
        // Now date is the actual date we want (not the time) so we can work out
60
 
        // what days we need to ask for from the grabber
61
 
 
62
 
        // Get a reference to yesterday's date (day before "date")
63
 
        Calendar yesterday = (Calendar) date.clone();
64
 
        yesterday.add(Calendar.DAY_OF_YEAR, -1);
65
 
 
66
 
        // Similarly get tomorrow
67
 
        Calendar tomorrow = (Calendar) date.clone();
68
 
        tomorrow.add(Calendar.DAY_OF_YEAR, 1);
69
 
 
70
 
        String date1str;
71
 
        String date2str;
72
 
 
73
 
        //FreeGuide.log.info( "grabber_start_time=" + grabber_start_time +
74
 
        //      " day_start_time=" + day_start_time );
75
 
 
76
 
        // See whether we need to grab yesterday or tomorrow
77
 
        if ( grabber_start_time.before( day_start_time,
78
 
                new Time(0, 0) ) ) {
79
 
 
80
 
            // Example:
81
 
            // grabber grabs midnight to midnight and we want to see 02:00 today
82
 
            // to 02:00 tomorrow: need to grab today and tomorrow
83
 
 
84
 
            date1str = ViewerFrame.fileDateFormat.format(date.getTime());
85
 
            date2str = ViewerFrame.fileDateFormat.format(
86
 
                    tomorrow.getTime());
87
 
 
88
 
            //FreeGuide.log.info( "Getting tomorrow data" );
89
 
 
90
 
        } else if( grabber_start_time.after( day_start_time,
91
 
                new Time(0, 0) ) ) {
92
 
 
93
 
            // Example:
94
 
            // grabber grabs 06:00 today to 06:00 tomorrow and we want to see
95
 
            // midnight to midnight: need to grab today and yesterday
96
 
 
97
 
            date1str = ViewerFrame.fileDateFormat.format(
98
 
                    yesterday.getTime());
99
 
            date2str = ViewerFrame.fileDateFormat.format(
100
 
                    date.getTime());
101
 
 
102
 
            //FreeGuide.log.info( "Getting yesterday data" );
103
 
 
104
 
        } else {
105
 
                        
106
 
                        // The days are perfectly matched so only parse one day.
107
 
                        
108
 
                        date1str = null;
109
 
                        date2str = ViewerFrame.fileDateFormat.format(
110
 
                    date.getTime() );
111
 
                        
112
 
                }
113
 
 
114
 
                String day1Filename;
115
 
                String day2Filename;
116
 
                
117
 
                if( date1str != null ) {
118
 
                        day1Filename = working_directory + fs + "tv-" +
119
 
                date1str + ".xmltv";
120
 
                } else {
121
 
                        day1Filename = null;
122
 
                }
123
 
 
124
 
        day2Filename = working_directory + fs + "tv-" +
125
 
                date2str + ".xmltv";
126
 
 
127
 
        String unprocFilename = working_directory + fs + "tv-unprocessed.xmltv";
128
 
 
129
 
                File day1File;
130
 
                File day2File;
131
 
                File unprocFile;
132
 
                
133
 
                if( day1Filename != null ) {
134
 
                        day1File = new File(day1Filename);
135
 
                } else {
136
 
                        day1File = null;
137
 
                }
138
 
                
139
 
        day2File = new File(day2Filename);
140
 
        unprocFile = new File(unprocFilename);
141
 
 
142
 
        // Parse any files that exist
143
 
 
144
 
        try {
145
 
            //ParserExceptions etc
146
 
 
147
 
            //DefaultHandler handler = new FreeGuideSAXHandler( this );
148
 
 
149
 
            SAXParserFactory factory = SAXParserFactory.newInstance();
150
 
 
151
 
            SAXParser saxParser = factory.newSAXParser();
152
 
 
153
 
                        boolean day1FileExists;
154
 
                        boolean day2FileExists;
155
 
                        
156
 
                        if( day1File != null ) {
157
 
                                day1FileExists = day1File.exists();
158
 
                        } else {
159
 
                                day1FileExists = false;
160
 
                        }
161
 
                        
162
 
            day2FileExists = day2File.exists();
163
 
 
164
 
            // If either day file exists (or both), parse it/them.  Otherwise
165
 
            // get the unproc. listings if they exist.
166
 
 
167
 
            if (day1FileExists) {
168
 
 
169
 
                                //FreeGuide.log.info( "Parsing " + day1Filename );
170
 
                                
171
 
                saxParser.parse(day1Filename, this);
172
 
 
173
 
            }
174
 
 
175
 
            if (day2FileExists) {
176
 
 
177
 
                                //FreeGuide.log.info( "Parsing " + day2Filename );
178
 
                                
179
 
                saxParser.parse(day2Filename, this);
180
 
 
181
 
            }
182
 
 
183
 
            if ((!day1FileExists) && (!day2FileExists) && unprocFile.exists()) {
184
 
 
185
 
                // The grabber must not be able to split into days,
186
 
                // so we'll deal with the unprocessed data.
187
 
                saxParser.parse(unprocFilename, this);
188
 
 
189
 
            }
190
 
        } catch (ParserConfigurationException e) {
191
 
            e.printStackTrace();
192
 
            // FIXME - error dialog!
193
 
        } catch (SAXException e) {
194
 
            e.printStackTrace();
195
 
            // FIXME - error dialog!
196
 
        } catch (java.io.IOException e) {
197
 
            e.printStackTrace();
198
 
            // FIXME - error dialog!
199
 
        }
200
 
        //try
201
 
 
202
 
    }
203
 
 
204
 
    // 
205
 
    /**
206
 
     *  Returns true if there was "enough" data for today and false if some was
207
 
     * missing.
208
 
     *
209
 
     *@return    true if there was enough data for today
210
 
     */
211
 
    public boolean hasData() {
212
 
 
213
 
        return (thereAreEarlyProgs && thereAreLateProgs);
214
 
    }
215
 
 
216
 
 
217
 
    // ----------------------------------------------------------------------
218
 
 
219
 
    /**
220
 
     *  Alter date to reflect if we are in another day's data (i.e. before the
221
 
     *  day start time) and set earliest and latest to the right values
222
 
     *  according to the day start time
223
 
     *
224
 
     *@param  nowDate  Description of the Parameter
225
 
     */
226
 
    public void updateDaySpan( Calendar nowDate ) {
227
 
 
228
 
        day_start_time = FreeGuide.prefs.misc.getTime(
229
 
                "day_start_time", new Time(6, 0));
230
 
 
231
 
        grabber_start_time = FreeGuide.prefs.misc.getTime(
232
 
                "grabber_start_time", new Time(0, 0));
233
 
 
234
 
        working_directory = FreeGuide.prefs.performSubstitutions(
235
 
                FreeGuide.prefs.misc.get("working_directory"));
236
 
 
237
 
        //earliest = GregorianCalendar.getInstance();
238
 
        //latest = GregorianCalendar.getInstance();
239
 
 
240
 
        date = (Calendar) nowDate.clone();
241
 
 
242
 
        // If we're before the day start time we actually want the previous day.
243
 
        //FreeGuideTime nowTime = new FreeGuideTime( date );
244
 
 
245
 
        //if( nowTime.before( day_start_time, new FreeGuideTime( 0, 0 ) ) ) {
246
 
 
247
 
        // If we need to adjust because our day start is before our grabber's
248
 
        //if( day_start_time.before(
249
 
        //              grabber_start_time, new FreeGuideTime( 0, 0 ) ) ) {
250
 
 
251
 
        // Set the time to the previous day, 1 hour after the day start time
252
 
        //      date.add( Calendar.DATE, -1 );
253
 
        //      date.set( Calendar.HOUR, day_start_time.getHours() + 1 );
254
 
 
255
 
        //}
256
 
 
257
 
        // Set earliest to the start time on the date
258
 
        earliest = (Calendar) date.clone();
259
 
 
260
 
        day_start_time.adjustCalendar(earliest);
261
 
 
262
 
        // Set latest to the start time on the day after the date
263
 
        latest = (Calendar) date.clone();
264
 
 
265
 
        latest.add(Calendar.DAY_OF_YEAR, 1);
266
 
 
267
 
        day_start_time.adjustCalendar(latest);
268
 
 
269
 
    }
270
 
 
271
 
 
272
 
    /**
273
 
     *  Description of the Method
274
 
     *
275
 
     *@param  nowDate  Description of the Parameter
276
 
     */
277
 
    private void setupHasDataStuff(Calendar nowDate) {
278
 
 
279
 
        // There must be a programme crossing over both of these times in order
280
 
        // for the day to be "covered" i.e. we don't need to download more.
281
 
        hasDataEarliest = (Calendar) earliest.clone();
282
 
        hasDataLatest   = (Calendar) latest.clone();
283
 
 
284
 
        // If it's today then hasDataEarliest is now-ish
285
 
        if( dayIsToday(nowDate) ) {
286
 
 
287
 
            hasDataEarliest.setTimeInMillis( nowDate.getTimeInMillis() );
288
 
 
289
 
        }
290
 
 
291
 
        // Now add an hour's grace to start time
292
 
        hasDataEarliest.add(Calendar.HOUR, 1);
293
 
 
294
 
        // and remove an hour from the end time
295
 
        hasDataLatest.add(Calendar.HOUR, -1);
296
 
 
297
 
    }
298
 
 
299
 
 
300
 
    /**
301
 
     *  Description of the Method
302
 
     *
303
 
     *@param  nowDate  Description of the Parameter
304
 
     *@return          Description of the Return Value
305
 
     */
306
 
    private boolean dayIsToday( Calendar iviewedDateTime ) {
307
 
 
308
 
        // First copy the datetime we were given because we may have to alter it
309
 
        Calendar viewedDateTime = GregorianCalendar.getInstance();
310
 
        viewedDateTime.setTimeInMillis( iviewedDateTime.getTimeInMillis() );
311
 
        
312
 
        // Now find the time of the datetime we were given
313
 
        Time viewedTime = new Time( viewedDateTime );
314
 
        if( viewedTime.before( day_start_time, new Time(0, 0) ) ) {
315
 
            
316
 
            viewedDateTime.add( Calendar.DATE, -1 );
317
 
 
318
 
        }
319
 
        
320
 
        // If we're before the day start time then go to the previous day
321
 
        
322
 
        Calendar nowDateTime = GregorianCalendar.getInstance();
323
 
        Time nowTime = new Time( nowDateTime );
324
 
 
325
 
        // If we're before the day start time then go to the previous day
326
 
        if( nowTime.before( day_start_time, new Time(0, 0) ) ) {
327
 
            
328
 
            nowDateTime.add( Calendar.DATE, -1 );
329
 
 
330
 
        }
331
 
        
332
 
        // Now check whether the dates are equal.
333
 
        return ( viewedDateTime.get(Calendar.YEAR)
334
 
                    == nowDateTime.get(Calendar.YEAR)
335
 
              && viewedDateTime.get(Calendar.DAY_OF_YEAR)
336
 
                    == nowDateTime.get(Calendar.DAY_OF_YEAR) );
337
 
    
338
 
    }
339
 
 
340
 
 
341
 
    // ----------------------------------------------------------------------
342
 
 
343
 
    /**
344
 
     *  Description of the Method
345
 
     */
346
 
    public void startDocument() {
347
 
        saxLoc = new String();
348
 
        channelIcons = new Hashtable();
349
 
    }
350
 
 
351
 
 
352
 
    //startDocument
353
 
 
354
 
    /**
355
 
     *  Description of the Method
356
 
     */
357
 
    public void endDocument() {
358
 
        saxLoc = null;
359
 
    }
360
 
 
361
 
 
362
 
    //endDocument
363
 
 
364
 
    /**
365
 
     *  Description of the Method
366
 
     *
367
 
     *@param  namespaceURI  Description of the Parameter
368
 
     *@param  sName         Description of the Parameter
369
 
     *@param  name          Description of the Parameter
370
 
     *@param  attrs         Description of the Parameter
371
 
     */
372
 
    public void startElement(String namespaceURI, String sName, String name,
373
 
            Attributes attrs) {
374
 
 
375
 
        saxLoc += ":" + name;
376
 
                
377
 
                data = "";
378
 
 
379
 
        //FreeGuide.log.info( saxLoc );
380
 
 
381
 
        if (saxLoc.equals(":tv:programme")) {
382
 
 
383
 
            currentProgramme = new Programme();
384
 
 
385
 
            // Prepare GregorianCalendars for start and end
386
 
            Calendar start = GregorianCalendar.getInstance();
387
 
            Calendar end = GregorianCalendar.getInstance();
388
 
 
389
 
            // Assume it has a channel
390
 
            String channelID = attrs.getValue("channel");
391
 
            currentProgramme.setChannelID(channelID);
392
 
            currentProgramme.addToChannelName(getChannelName(channelID));
393
 
 
394
 
            try {
395
 
 
396
 
                // Assume is has a start time
397
 
                start = parseDate(attrs.getValue("start"));
398
 
 
399
 
                // Don't assume it has an end time
400
 
                if (attrs.getIndex("stop") == -1
401
 
                        || attrs.getValue("stop").equals("+0100")) {
402
 
                    // Also hack around bug in de grabber
403
 
 
404
 
                    // Give it a fake end time, half an hour after the start
405
 
                    end.setTimeInMillis(start.getTimeInMillis());
406
 
                    end.add(Calendar.MINUTE, 30);
407
 
 
408
 
                } else {
409
 
 
410
 
                    end = parseDate(attrs.getValue("stop"));
411
 
                    //Watch out for missing end dates!
412
 
                    if (end.before(start)) {
413
 
                        // Give it a fake end time, half an hour after the start
414
 
                        end.setTimeInMillis(start.getTimeInMillis());
415
 
                        end.add(Calendar.MINUTE, 30);
416
 
                    }
417
 
                }
418
 
 
419
 
            } catch (java.text.ParseException e) {
420
 
                e.printStackTrace();
421
 
                currentProgramme = null;
422
 
 
423
 
                return;
424
 
            }
425
 
 
426
 
            if( start.before(hasDataEarliest) ) {
427
 
 
428
 
                thereAreEarlyProgs = true;
429
 
 
430
 
            }
431
 
 
432
 
            if( end.after(hasDataLatest) ) {
433
 
 
434
 
                thereAreLateProgs = true;
435
 
 
436
 
            }
437
 
 
438
 
            currentProgramme.setStart(start);
439
 
            currentProgramme.setEnd(end);
440
 
 
441
 
        } else if (saxLoc.equals(":tv:channel")) {
442
 
 
443
 
            String id = attrs.getValue("id");
444
 
 
445
 
            tmpChannelID = id;
446
 
 
447
 
        } else if (saxLoc.equals(":tv:channel:icon")) {
448
 
 
449
 
                String URL = attrs.getValue("src");
450
 
                if (URL != null)
451
 
                        channelIcons.put(tmpChannelID,URL);
452
 
 
453
 
        } else if (saxLoc.equals(":tv:programme:previously-shown")) {
454
 
 
455
 
            if (currentProgramme != null) {
456
 
                currentProgramme.setPreviouslyShown(true);
457
 
            }
458
 
            
459
 
        } else if (saxLoc.equals(":tv:programme:rating")) {
460
 
 
461
 
            if (currentProgramme != null) {
462
 
                String ratingsystem = attrs.getValue("system");
463
 
                if (ratingsystem != null && ratingsystem.equalsIgnoreCase("MPAA")) {
464
 
                    currentProgramme.setIsMovie(true);
465
 
                }
466
 
            }
467
 
            
468
 
                } else if (saxLoc.equals(":tv:programme:subtitles")) {
469
 
 
470
 
            if (currentProgramme != null) {
471
 
                
472
 
                currentProgramme.setSubtitled( true );
473
 
                
474
 
            }
475
 
        
476
 
                } else if (saxLoc.equals(":tv:programme:icon")) {
477
 
                        
478
 
                        if (currentProgramme != null && attrs.getValue("src") != null)
479
 
                                currentProgramme.setIconURL(attrs.getValue("src"));
480
 
                        
481
 
                } else if ( saxLoc.equals(":tv:programme:desc")
482
 
            || saxLoc.equals(":tv:programme:title")
483
 
            || saxLoc.equals(":tv:programme:sub-title")
484
 
            || saxLoc.equals(":tv:programme:category")
485
 
            || saxLoc.startsWith(":tv:programme:rating")
486
 
            || saxLoc.equals(":tv:programme:star-rating")
487
 
            || saxLoc.equals(":tv:programme:star-rating:value")
488
 
            || saxLoc.equals(":tv:programme:url") )
489
 
        {
490
 
            
491
 
            // Do nothing - dealt with in endElement
492
 
            
493
 
        } else if( saxLoc.matches( ":tv:programme:[^:]*" ) ) {
494
 
            
495
 
            //FreeGuide.log.info( saxLoc );
496
 
            
497
 
            // Remember any unrecognised data
498
 
            if (currentProgramme != null && attrs.getLength() > 0) {
499
 
                
500
 
                currentProgramme.startElement( name, attrs );
501
 
                
502
 
            }
503
 
            
504
 
        }
505
 
        //if
506
 
 
507
 
    }
508
 
 
509
 
 
510
 
    //startElement
511
 
 
512
 
    /**
513
 
     *  Description of the Method
514
 
     *
515
 
     *@param  strDate                       Description of the Parameter
516
 
     *@return                               Description of the Return Value
517
 
     *@exception  java.text.ParseException  Description of the Exception
518
 
     */
519
 
    private Calendar parseDate(String strDate)
520
 
             throws java.text.ParseException {
521
 
 
522
 
        Calendar ans = GregorianCalendar.getInstance();
523
 
                 
524
 
        // First check for a time without any timezone or seconds
525
 
        if( strDate.matches( "\\A\\d{12}\\z" ) ) {
526
 
            
527
 
            ans.setTime(
528
 
                new SimpleDateFormat( "yyyyMMddHHmm" ).parse( strDate ) );
529
 
            
530
 
            // Now try without timezone or seconds
531
 
        } else if( strDate.matches( "\\A\\d{14}\\z" ) ) {
532
 
            
533
 
            ans.setTime(
534
 
                new SimpleDateFormat( "yyyyMMddHHmmss" ).parse( strDate ) );
535
 
            
536
 
        } else {
537
 
            
538
 
            try {
539
 
                
540
 
                ans.setTime(
541
 
                    new SimpleDateFormat("yyyyMMddHHmmss z").parse( strDate ) );
542
 
                
543
 
             } catch (java.text.ParseException g) {
544
 
                 
545
 
                 ans.setTime(
546
 
                    new SimpleDateFormat("yyyyMMddHHmmss Z").parse( strDate ) );
547
 
                 
548
 
             }
549
 
        }
550
 
 
551
 
        return ans;
552
 
    }
553
 
 
554
 
 
555
 
    /**
556
 
     *  Description of the Method
557
 
     *
558
 
     *@param  namespaceURI  Description of the Parameter
559
 
     *@param  sName         Description of the Parameter
560
 
     *@param  name          Description of the Parameter
561
 
     */
562
 
    public void endElement(String namespaceURI, String sName, String name) {
563
 
 
564
 
        //FreeGuide.log.info(name);
565
 
 
566
 
        if (saxLoc.equals(":tv:programme")) {
567
 
 
568
 
            if (currentProgramme.getEnd().after(earliest) &&
569
 
                    currentProgramme.getStart().before(latest))
570
 
            {
571
 
 
572
 
                if( programmeNotAlreadyEntered( currentProgramme ) ) {
573
 
                    programmes.add(currentProgramme);
574
 
                }
575
 
            }
576
 
 
577
 
            currentProgramme = null;
578
 
                        
579
 
        } else if (saxLoc.equals(":tv:programme:title")) {
580
 
 
581
 
            if (currentProgramme != null) {
582
 
                currentProgramme.setTitle( data );
583
 
            }
584
 
            
585
 
                } else if (saxLoc.equals(":tv:programme:sub-title")) {
586
 
 
587
 
            if (currentProgramme != null) {
588
 
                currentProgramme.setSubTitle( data );
589
 
            }
590
 
        } else if (saxLoc.equals(":tv:programme:desc")) {
591
 
 
592
 
            if (currentProgramme != null) {
593
 
                currentProgramme.addDesc( data );
594
 
            }
595
 
        } else if (saxLoc.equals(":tv:programme:category")) {
596
 
 
597
 
            if (currentProgramme != null) {
598
 
                currentProgramme.addCategory( data );
599
 
                if( data.equalsIgnoreCase("Film")
600
 
                    || data.equalsIgnoreCase("CINE") )
601
 
                {
602
 
                    currentProgramme.setIsMovie(true);
603
 
                }
604
 
            }
605
 
        } else if (saxLoc.equals(":tv:programme:star-rating:value")) {
606
 
 
607
 
            if (currentProgramme != null) {
608
 
                currentProgramme.setStarRating( data );
609
 
            }
610
 
                
611
 
                //} else if (saxLoc.equals(":tv:programme:episode-num")) {
612
 
                        // FIXME - fill in here
613
 
 
614
 
        } else if (saxLoc.equals(":tv:programme:url")) {
615
 
 
616
 
                        if (currentProgramme != null) {
617
 
                                
618
 
                                try {
619
 
                                        
620
 
                        currentProgramme.setLink(new URL(data));
621
 
                                
622
 
                                } catch(java.net.MalformedURLException e) {
623
 
                                        e.printStackTrace();
624
 
                                }
625
 
            }
626
 
 
627
 
                } else if( saxLoc.equals(":tv:programme:subtitles") 
628
 
                || saxLoc.equals(":tv:programme:previously-shown")
629
 
                || saxLoc.startsWith(":tv:programme:rating")
630
 
                || saxLoc.equals(":tv:programme:star-rating")
631
 
                                || saxLoc.equals(":tv:programme:icon") )
632
 
        {
633
 
            
634
 
            // Do nothing - dealt with in startElement or elsewhere
635
 
            
636
 
        } else if( saxLoc.equals(":tv:channel:display-name") ) {
637
 
 
638
 
            // Remember the name of the channel we're looking at
639
 
            addChannelName(tmpChannelID, data);
640
 
 
641
 
                } else if( saxLoc.matches( ":tv:programme:[^:]*" ) ) {
642
 
                // Ending an unknown main tag
643
 
            
644
 
            if( currentProgramme != null ) {
645
 
                currentProgramme.endElement( name, "", data );
646
 
            }
647
 
            
648
 
        } else {
649
 
            
650
 
            Pattern patt = Pattern.compile( ":tv:programme:([^:]+):(.+)" );
651
 
            Matcher mat  = patt.matcher( saxLoc );
652
 
            
653
 
            // If we're looking at an unknown tag of a programme
654
 
            if (mat.matches() && currentProgramme != null && data != null && !data.equals("")) {
655
 
                    // Ending an unknown subtag
656
 
                
657
 
                String mainTag = mat.group( 1 );
658
 
                    
659
 
                currentProgramme.endElement( mainTag, mat.group(2), data );
660
 
                data = "";
661
 
            }
662
 
            
663
 
        }
664
 
                
665
 
                if (saxLoc.endsWith(name)) {
666
 
 
667
 
            saxLoc = saxLoc.substring(0, saxLoc.length() - (name.length() + 1));
668
 
 
669
 
        } else {
670
 
            parseError();
671
 
        }
672
 
        //if
673
 
 
674
 
        //FreeGuide.log.info("endElement END");
675
 
 
676
 
    }
677
 
 
678
 
    private boolean programmeNotAlreadyEntered( Programme programme ) {
679
 
        
680
 
        Iterator iter = programmes.iterator();
681
 
        
682
 
        while( iter.hasNext() ) {
683
 
            
684
 
            Programme prog = (Programme)(iter.next());
685
 
            
686
 
            if( prog.equals( programme ) ) {
687
 
                return false;
688
 
            }
689
 
            
690
 
        }
691
 
        
692
 
        return true;
693
 
    }
694
 
    
695
 
    
696
 
    /**
697
 
     *  Description of the Method
698
 
     *
699
 
     *@param  ch      Description of the Parameter
700
 
     *@param  start   Description of the Parameter
701
 
     *@param  length  Description of the Parameter
702
 
     */
703
 
    public void characters(char[] ch, int start, int length) {
704
 
        data += new String(ch, start, length);
705
 
    }
706
 
 
707
 
 
708
 
    //characters
709
 
 
710
 
    // -----------------------------------------------------------------------
711
 
 
712
 
    /**
713
 
     *  Gets the channelIDs attribute of the XMLTVLoader object
714
 
     *
715
 
     *@return    The channelIDs value
716
 
     */
717
 
    public Vector getChannelIDs() {
718
 
        return channelIDs;
719
 
    }
720
 
 
721
 
 
722
 
    /**
723
 
     *  Gets the channelNames attribute of the XMLTVLoader object
724
 
     *
725
 
     *@return    The channelNames value
726
 
     */
727
 
    public Vector getChannelNames() {
728
 
        return channelNames;
729
 
    }
730
 
 
731
 
 
732
 
    /**
733
 
     *  Adds a feature to the ChannelName attribute of the XMLTVLoader object
734
 
     *
735
 
     *@param  channelID    The feature to be added to the ChannelName attribute
736
 
     *@param  channelName  The feature to be added to the ChannelName attribute
737
 
     */
738
 
    private void addChannelName(String channelID, String channelName) {
739
 
 
740
 
                int i = channelIDs.indexOf(channelID);
741
 
                
742
 
        if ( i == -1) {
743
 
 
744
 
            channelIDs.add(channelID);
745
 
            channelNames.add(channelName);
746
 
 
747
 
        }
748
 
    }
749
 
 
750
 
 
751
 
    /**
752
 
     *  Gets the channelName attribute of the XMLTVLoader object
753
 
     *
754
 
     *@param  i  Description of the Parameter
755
 
     *@return    The channelName value
756
 
     */
757
 
    public String getChannelName(int i) {
758
 
 
759
 
        return (String) channelNames.get(i);
760
 
    }
761
 
 
762
 
 
763
 
    /**
764
 
     *  Gets the noChannels attribute of the XMLTVLoader object
765
 
     *
766
 
     *@return    The noChannels value
767
 
     */
768
 
    public int getNoChannels() {
769
 
 
770
 
        return channelIDs.size();
771
 
    }
772
 
 
773
 
 
774
 
    /**
775
 
     *  Gets the channelNo attribute of the XMLTVLoader object
776
 
     *
777
 
     *@param  channelID  Description of the Parameter
778
 
     *@return            The channelNo value
779
 
     */
780
 
    public int getChannelNo(String channelID) {
781
 
 
782
 
        return channelIDs.indexOf(channelID);
783
 
    }
784
 
 
785
 
 
786
 
    /**
787
 
     *  Sets the channelSetName attribute of the XMLTVLoader object
788
 
     *
789
 
     *@param  name  The new channelSetName value
790
 
     */
791
 
    public void setChannelSetName(String name) {
792
 
        return;
793
 
    }
794
 
 
795
 
 
796
 
    /**
797
 
     *  Gets the channelSetName attribute of the XMLTVLoader object
798
 
     *
799
 
     *@return    The channelSetName value
800
 
     */
801
 
    public String getChannelSetName() {
802
 
        return ViewerFrame.CHANNEL_SET_ALL_CHANNELS;
803
 
    }
804
 
 
805
 
 
806
 
    /**
807
 
     *  Returns the name of the channel whose ID is supplied.
808
 
     *
809
 
     *@param  channelID  Description of the Parameter
810
 
     *@return            The channelName value
811
 
     */
812
 
    public String getChannelName(String channelID) {
813
 
                
814
 
        int ch = channelIDs.indexOf(channelID);
815
 
 
816
 
        if (ch == -1) {
817
 
 
818
 
            addChannelName(channelID, channelID);
819
 
 
820
 
            return channelID;
821
 
        } else {
822
 
 
823
 
            String chName = (String) channelNames.get(ch);
824
 
 
825
 
            if (chName == null) {
826
 
 
827
 
                return channelID;
828
 
            } else {
829
 
 
830
 
                return chName;
831
 
            }
832
 
 
833
 
        }
834
 
 
835
 
    }
836
 
    
837
 
    /**
838
 
     * to get the Icon URL of the channel
839
 
     * @param channelID the Id of the channel to get URL for
840
 
     * @return the URL as a string;
841
 
     */
842
 
    public String getChannelIcon(String channelID){
843
 
        if (channelID == null || channelIcons == null) return null;
844
 
        return (String)channelIcons.get(channelID);
845
 
    }
846
 
 
847
 
 
848
 
    /**
849
 
     *  Description of the Method
850
 
     */
851
 
    private void parseError() {
852
 
        FreeGuide.log.severe("ViewerFrame - Error parsing XML.");
853
 
        System.exit(1);
854
 
    }
855
 
 
856
 
 
857
 
    // ---------------------------------------------------------------
858
 
 
859
 
    private String saxLoc = "";
860
 
    // Holds our current pos in the XML hierarchy
861
 
    private String tmpChannelID;
862
 
        private String data;
863
 
 
864
 
    private Programme currentProgramme;
865
 
    // The programme we're loading in now
866
 
 
867
 
    String fs = System.getProperty("file.separator");
868
 
 
869
 
    private Time day_start_time;
870
 
 
871
 
    private Time grabber_start_time;
872
 
 
873
 
    private String working_directory;
874
 
 
875
 
    /**
876
 
     *  Description of the Field
877
 
     */
878
 
    public Vector programmes;
879
 
    // Vector of loaded FreeGuideProgrammes
880
 
    private Vector channelIDs;
881
 
    // The IDs of the channels
882
 
    private Vector channelNames;
883
 
    // The names of the channels
884
 
    private Hashtable channelIcons;
885
 
 
886
 
    /**
887
 
     *  Description of the Field
888
 
     */
889
 
    public Calendar date;
890
 
    // The actual date we want (YMD, ignore time)
891
 
 
892
 
    /**
893
 
     *  Description of the Field
894
 
     */
895
 
    public Calendar earliest;
896
 
    // The time of the start of this day
897
 
    /**
898
 
     *  Description of the Field
899
 
     */
900
 
    public Calendar latest;
901
 
    // The time of the end of this day
902
 
 
903
 
    private boolean thereAreEarlyProgs;
904
 
    // 2 flags which indicate whether or
905
 
    private boolean thereAreLateProgs;
906
 
    // not there are programmes at the
907
 
    // beg. and end of today.
908
 
 
909
 
    private Calendar hasDataEarliest;
910
 
    // The start of the day in terms of
911
 
    // Whether there is enough data today
912
 
    private Calendar hasDataLatest;
913
 
    // Similarly the end
914
 
 
915
 
}
916