1 /*
2  *  FreeGuide J2
3  *
4  *  Copyright (c) 2001-2004 by Andy Balaam and the FreeGuide contributors
5  *
6  *  freeguide-tv.sourceforge.net
7  *
8  *  Released under the GNU General Public License
9  *  with ABSOLUTELY NO WARRANTY.
10  *
11  *  See the file COPYING for more information.
12  */
13 package freeguide.common.lib.fgspecific.selection;
14 
15 import freeguide.common.lib.fgspecific.Application;
16 import freeguide.common.lib.fgspecific.data.TVProgramme;
17 import freeguide.common.lib.general.Time;
18 
19 import java.text.Collator;
20 import java.util.Calendar;
21 import java.util.Comparator;
22 import java.util.Date;
23 import java.util.GregorianCalendar;
24 import java.util.Locale;
25 import java.util.regex.Pattern;
26 
27 import java.util.Map;
28 import java.util.Collection;
29 /**
30  * FreeGuideFavourite A description of a favourite TV program, vague or
31  * specific.
32  *
33  * @author Andy Balaam
34  * @version 3
35  */
36 public class Favourite
37 {
38     // ------------------------------------------------------------------------
39     /** The user-specified name of this favourite */
40     public String name;
41 
42     /** Exact match for the title */
43     public String titleString;
44 
45     /** String contained in the title */
46     public String titleContains;
47 
48     /** Regular expression to match the title */
49     public String titleRegex;
50     transient protected Pattern titleRegexPattern;
51 
52     /** String contained in the description or in the extraTags */
53     public String descriptionContains;
54 
55     /** The channel it must be on */
56     public String channelID;
57 
58     /** The time it must be on after */
59     public Time afterTime = new Time(  );
60 
61     /** The time it must be on before */
62     public Time beforeTime = new Time(  );
63 
64     /** Day of week, or -1 if any. */
65     public int dayOfWeek = -1;
66 
67     /**
68      * Constructor for the Favourite object
69      */
Favourite( )70     public Favourite(  )
71     {
72     }
73 
74     /**
75      * DOCUMENT_ME!
76      *
77      * @return DOCUMENT_ME!
78      */
clone( )79     public Object clone(  )
80     {
81         final Favourite result = new Favourite(  );
82         result.name = name;
83         result.titleString = titleString;
84         result.titleContains = titleContains;
85         result.titleRegex = titleRegex;
86         result.descriptionContains = descriptionContains;
87         result.channelID = channelID;
88         result.afterTime = afterTime;
89         result.beforeTime = beforeTime;
90         result.dayOfWeek = dayOfWeek;
91 
92         return result;
93     }
94 
getTitleRegexPattern( )95     protected Pattern getTitleRegexPattern(  )
96     {
97         if( ( titleRegexPattern == null ) && ( titleRegex != null ) )
98         {
99             titleRegexPattern = Pattern.compile( titleRegex );
100         }
101 
102         return titleRegexPattern;
103     }
104 
105     // ------------------------------------------------------------------------
106     /**
107      * matches Decides whether or not a programme matches this
108      * favourite.
109      *
110      * @param prog the programme to check
111      *
112      * @return true if this programme matches this favourite
113      */
matches( TVProgramme prog )114     public boolean matches( TVProgramme prog )
115     {
116         String progTitle = prog.getTitle(  );
117 
118         // Match the title exactly
119         if( ( titleString != null ) && !titleString.equals( progTitle ) )
120         {
121             return false;
122         }
123 
124         // Match the title to containing a string
125         if(
126             ( titleContains != null )
127                 && ( progTitle.indexOf( titleContains ) == -1 ) )
128         {
129             return false;
130         }
131 
132         // Match the title to a regular expression
133         if(
134             ( titleRegex != null )
135                 && !getTitleRegexPattern(  ).matcher( progTitle ).matches(  ) )
136         {
137             return false;
138         }
139 
140         // Matches if the description or anything else in extraTags (like the
141         // actor, producer, writer, or episode number) contains the string.
142         if( !descriptionOrTagsMatch( prog ) )
143         {
144             return false;
145         }
146 
147         // Match the channel ID
148         if(
149             ( channelID != null )
150                 && !channelID.equals( prog.getChannel(  ).getID(  ) ) )
151         {
152             return false;
153         }
154 
155         Time progStartTime = new Time( new Date( prog.getStart(  ) ) );
156 
157         // Match the time it must be after
158         if( !afterTime.isEmpty(  ) && afterTime.after( progStartTime ) )
159         {
160             return false;
161         }
162 
163         // Match the time it must be before
164         if( !beforeTime.isEmpty(  ) && beforeTime.before( progStartTime ) )
165         {
166             return false;
167         }
168 
169         Calendar cal = GregorianCalendar.getInstance(  );
170         cal.setTimeZone( Application.getInstance(  ).getTimeZone(  ) );
171         cal.setTimeInMillis( prog.getStart(  ) );
172 
173         // Match the day of the week
174         if(
175             ( dayOfWeek != -1 )
176                 && ( dayOfWeek != cal.get( Calendar.DAY_OF_WEEK ) ) )
177         {
178             return false;
179         }
180 
181         return true;
182     }
183 
184     // ------------------------------------------------------------------------
185     // Accessors
186     /**
187      * Gets the name attribute of the Favourite object
188      *
189      * @return The name value
190      */
getName( )191     public String getName(  )
192     {
193         return name;
194     }
195 
196     /**
197      * Gets the titleString attribute of the Favourite object
198      *
199      * @return The titleString value
200      */
getTitleString( )201     public String getTitleString(  )
202     {
203         return titleString;
204     }
205 
206     /**
207      * Gets the titleContains attribute of the Favourite object
208      *
209      * @return The titleContains value
210      */
getTitleContains( )211     public String getTitleContains(  )
212     {
213         return titleContains;
214     }
215 
216     /**
217      * Gets the titleRegex attribute of the Favourite object
218      *
219      * @return The titleRegex value
220      */
getTitleRegex( )221     public String getTitleRegex(  )
222     {
223         return titleRegex;
224     }
225 
getDescriptionContains( )226     public String getDescriptionContains(  )
227     {
228         return descriptionContains;
229     }
230 
231     /**
232      * Gets the channel attribute of the Favourite object
233      *
234      * @return The channel value
235      */
getChannelID( )236     public String getChannelID(  )
237     {
238         return channelID;
239     }
240 
241     /**
242      * Gets the afterTime attribute of the Favourite object
243      *
244      * @return The afterTime value
245      */
getAfterTime( )246     public Time getAfterTime(  )
247     {
248         return afterTime;
249     }
250 
251     /**
252      * Gets the beforeTime attribute of the Favourite object
253      *
254      * @return The beforeTime value
255      */
getBeforeTime( )256     public Time getBeforeTime(  )
257     {
258         return beforeTime;
259     }
260 
261     /**
262      * Gets the dayOfWeek attribute of the Favourite object
263      *
264      * @return The dayOfWeek value
265      */
getDayOfWeek( )266     public int getDayOfWeek(  )
267     {
268         return dayOfWeek;
269     }
270 
271     /**
272      * Sets the name attribute of the Favourite object
273      *
274      * @param name The new name value
275      */
setName( String name )276     public void setName( String name )
277     {
278         this.name = name;
279     }
280 
281     /**
282      * Sets the titleString attribute of the Favourite object
283      *
284      * @param titleString The new titleString value
285      */
setTitleString( String titleString )286     public void setTitleString( String titleString )
287     {
288         this.titleString = titleString;
289     }
290 
291     /**
292      * Sets the titleContains attribute of the Favourite object
293      *
294      * @param titleContains The new titleContains value
295      */
setTitleContains( String titleContains )296     public void setTitleContains( String titleContains )
297     {
298         this.titleContains = titleContains;
299     }
300 
301     /**
302      * Sets the titleRegex attribute of the Favourite object
303      *
304      * @param titleRegex The new titleRegex value
305      */
setTitleRegex( String titleRegex )306     public void setTitleRegex( String titleRegex )
307     {
308         this.titleRegex = titleRegex;
309         this.titleRegexPattern = null;
310     }
311 
setDescriptionContains( String descriptionContains )312     public void setDescriptionContains( String descriptionContains )
313     {
314         this.descriptionContains = descriptionContains;
315     }
316 
317     /**
318      * Sets the channelID attribute of the Favourite object
319      *
320      * @param channelID The new channelID value
321      */
setChannelID( String channelID )322     public void setChannelID( String channelID )
323     {
324         this.channelID = channelID;
325     }
326 
327     /**
328      * Sets the afterTime attribute of the Favourite object
329      *
330      * @param afterTime The new afterTime value
331      */
setAfterTime( Time afterTime )332     public void setAfterTime( Time afterTime )
333     {
334         this.afterTime = afterTime;
335     }
336 
337     /**
338      * Sets the beforeTime attribute of the Favourite object
339      *
340      * @param beforeTime The new beforeTime value
341      */
setBeforeTime( Time beforeTime )342     public void setBeforeTime( Time beforeTime )
343     {
344         this.beforeTime = beforeTime;
345     }
346 
347     /**
348      * Sets the dayOfWeek attribute of the Favourite object
349      *
350      * @param dayOfWeek The new dayOfWeek value
351      */
setDayOfWeek( int dayOfWeek )352     public void setDayOfWeek( int dayOfWeek )
353     {
354         this.dayOfWeek = dayOfWeek;
355     }
356 
357     public static class FavouriteComparator implements Comparator
358     {
compare( Object o1, Object o2 )359         public int compare( Object o1, Object o2 )
360         {
361            Favourite f1 = (Favourite)o1;
362            Favourite f2 = (Favourite)o2;
363 
364            return Collator.getInstance( Locale.getDefault() ).compare(
365                f1.getName(), f2.getName() );
366         }
367     }
368 
GetNameComparator()369     public static Comparator GetNameComparator()
370     {
371         return new FavouriteComparator();
372     }
373     // The day of the week it's on
374 
375 
376     /**
377      * descriptionOrTagsMatch decides if a description (ultimately entered by
378      * the user) is contained in a program's Description or ExtraTags.
379      *
380      * @param prog the programme whose description we will check
381      *
382      * @return true if this programme matches this favourite's description
383      *         field, or the descriptionContains field is empty.
384      */
descriptionOrTagsMatch( TVProgramme prog )385     public boolean descriptionOrTagsMatch( TVProgramme prog )
386     {
387         if( descriptionContains == null )
388         {
389             // If there is no requirement for the description to match
390             // anything, we "match".
391             return true;
392         }
393 
394         String progDescription = prog.getDescription(  );
395         Map progExtraTags = prog.getExtraTags(  );
396 
397         if(
398             progDescription != null &&
399             progDescription.contains( descriptionContains )
400         )
401         {
402             return true;
403         }
404 
405         if(
406             progExtraTags != null &&
407             matchInExtraTags( progExtraTags.values(  ), descriptionContains )
408         )
409         {
410             return true;
411         }
412 
413         return false;
414     }
415 
416     /**
417      * Searches for the supplied description in the extra tags map of a
418      * programme.
419      *
420      * @param tags the programme to check
421      * @param description the description to match
422      *
423      * @return true if the supplied description appears in one of the tags
424      *         in the map supplied.  False otherwise.
425      */
matchInExtraTags( Collection tags, String description )426     public boolean matchInExtraTags( Collection tags, String description )
427     {
428         for( Object tag : tags )
429         {
430             Map hashOfAttrs = (Map)tag;
431             for( Object attrValue : hashOfAttrs.values( ) )
432             {
433                 String s = (String)attrValue;
434                 if( s.indexOf( description ) != -1 )
435                 {
436                     return true;
437                 }
438             }
439         }
440 
441         return false;
442     }
443 }
444