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