View Javadoc
1 /*** 2 * Created by IntelliJ IDEA. 3 * User: Lennart 4 * Date: 19-aug-2003 5 * Time: 14:26:00 6 */ 7 package comics; 8 9 /* 10 * CVS information: 11 * 12 * $Revision: 1.5 $ 13 * $Date: 2003/12/03 23:05:08 $ 14 */ 15 16 import comics.interfaces.DayRoller; 17 import comics.interfaces.ComicGrabberEngine; 18 import comics.core.GregorianDayRoller; 19 import comics.core.ComicURLFactory; 20 import comics.core.ComicGrabberEngineImplementation; 21 import comics.core.ComicImage; 22 23 import java.util.*; 24 import java.io.*; 25 import java.net.URL; 26 import java.text.SimpleDateFormat; 27 import java.text.ParseException; 28 29 /*** 30 * This class grabs a complete history of comics off the UComics website. 31 * 32 * @author Lennart Martens 33 */ 34 public class ComicGrabber { 35 36 /*** 37 * Main method is the entry point for the application. 38 * 39 * @param args String[] with the start-up args. 40 */ 41 public static void main(String[] args) { 42 // Check the start-up args. 43 if(args == null || (args.length != 2 && args.length != 3)) { 44 System.err.println("\n\nUsage:\n\tComicGrabber <ucomics_comic_abbreviation> <output_path> [startdate_in_dd/MM/yyyy]"); 45 System.err.println("\n\t\tOR\n"); 46 System.err.println("\tComicGrabber @<details_file> <output_path>"); 47 System.exit(1); 48 } 49 // Get the arguments. 50 String comicName = args[0]; 51 File parent = new File(args[1]); 52 // Check whether the output folder exists. 53 if(!parent.exists()) { 54 System.err.println("\n\nThe output folder you specified ('" + args[1] + "') does not exist!\n\n"); 55 System.exit(1); 56 } 57 // Okay, we've gotten so far. Now create a DayRoller to use, as well as a ComicGrabberEngine. 58 // Right now we'll always go to UComics. 59 ComicGrabberEngine engine = new ComicGrabberEngineImplementation(); 60 Collection allComics = new ArrayList(); 61 62 // Is the date argument present? 63 Date startdate = null; 64 if (args.length == 3 && args[2] != null) { 65 try { 66 startdate = new SimpleDateFormat("dd/MM/yyyy").parse(args[2]); 67 } 68 catch (ParseException pe) { 69 //Idiot's guide to using our program 70 System.err.println("\n\nPlease format date: ('" + args[2] + "') like: dd/MM/yyyy\n\n"); 71 System.exit(1); 72 } 73 } 74 if(args.length == 2 && comicName.startsWith("@")) { 75 // Okay, read the input file. 76 try { 77 BufferedReader br = new BufferedReader(new FileReader(comicName.substring(1))); 78 String line = null; 79 while((line = br.readLine()) != null) { 80 // Trim the line. 81 line = line.trim(); 82 // Skip empty lines and comments. 83 if(line.equals("") || line.startsWith("!") || line.startsWith("#")) { 84 continue; 85 } else { 86 // Okay, line should be meaningful. 87 // Try to parse it. 88 // Format should be: 89 // <comiccname> <comma_separeted_applicable_days_without_spaces> [<optional_startdate>] 90 StringTokenizer main = new StringTokenizer(line, " "); 91 int count = main.countTokens(); 92 if(count != 2 && count != 3) { 93 System.err.println(" *** Could not parse line '" + line + "'. Skipping it."); 94 } else { 95 String comic = main.nextToken().trim(); 96 String daysString = main.nextToken().trim(); 97 String dateString = null; 98 Date date = null; 99 int[] days = null; 100 StringTokenizer inner = new StringTokenizer(daysString, ","); 101 int countInner = inner.countTokens(); 102 if(inner.countTokens() == 0) { 103 System.err.println(" *** No applicable days found, skipping line '" + line + "'."); 104 } else if(countInner >= 1) { 105 String token = inner.nextToken().trim(); 106 int counter = 0; 107 if(countInner > 1 || !token.equalsIgnoreCase("all")) { 108 days = new int[countInner]; 109 while(true) { 110 int day = parseDay(token); 111 if(day < 0) { 112 System.err.println(" *** Unable to parse day String '" + token + "' in line, skipping line '" + line + "'. "); 113 } else { 114 days[counter] = day; 115 } 116 counter++; 117 if(inner.hasMoreTokens()) { 118 token = inner.nextToken().trim(); 119 } else { 120 break; 121 } 122 } 123 } 124 } 125 // If there's a startdate, parse it. 126 if(count == 3) { 127 dateString = main.nextToken().trim(); 128 try { 129 date = new SimpleDateFormat("dd/MM/yyyy").parse(dateString); 130 } catch(ParseException pe) { 131 System.err.println(" *** Incorrectly formatted date found (" + dateString + "), skipping line '" + line +"'."); 132 } 133 } 134 allComics.add(new Object[]{comic, date, days}); 135 } 136 } 137 } 138 } catch(IOException ioe) { 139 System.err.println("Unable to read the specified file (" + comicName.substring(1) + "): " + ioe.getMessage()); 140 } 141 } else { 142 // Just one comic to do. 143 allComics.add(new Object[]{comicName, startdate, null}); 144 } 145 146 // The stage is set. Let's get going. 147 Iterator iter = allComics.iterator(); 148 while(iter.hasNext()){ 149 Object[] value = (Object[])iter.next(); 150 String comic = (String)value[0]; 151 DayRoller roller = new GregorianDayRoller(); 152 // See if we had a startdate. 153 Object date = value[1]; 154 if(date != null) { 155 roller.setStartDate((Date)value[2]); 156 } else { 157 // No startdate set, take today. 158 roller.setStartDate(new Date()); 159 } // See if we had a list of applicable days. 160 Object days = value[2]; 161 if(days != null) { 162 roller.setApplicableDays((int[])value[1]); 163 } else { 164 // No applicable days. 165 roller.setApplicableDays(null); 166 } 167 roller.getCurrentDate(); 168 try { 169 // This variable is used to see when it's done grabbing. 170 int previousError = 0; 171 // This variable keeps track of the previous month. Each new month grabbed, gets a println. 172 int previousMonth = roller.getCurrentMonth(); 173 int previousYear = roller.getCurrentYear(); 174 // Total error count while retrieving. 175 int totalError = 0; 176 // Keep cycling. 177 //int previousRoll = 5; // Captain ribman, starting on Tuesday = 5; Thursday = 2. 178 while(previousError < 14) { 179 // Each retrieval attempt has its own 'try-catch' block, to keep an isolated failure from 180 // wrecking the entire program. 181 try { 182 // We need the year separately in the retrieval process, and the month is used for printing 183 // statements. 184 int year = roller.getCurrentYear(); 185 int month = roller.getCurrentMonth(); 186 // Make sure the notation is zero-primed for single-digit numbers, eg. '08'. 187 String previousMonthString = ((previousMonth < 10)?"0":"") + Integer.toString(previousMonth); 188 String currentMonthString = ((month < 10)?"0":"") + Integer.toString(month); 189 // Some user-friendly statements. 190 if(month < previousMonth || year < previousYear) { 191 System.out.println("Grabbed " + previousMonthString + "/" + previousYear + " for comic '" + comic + "'."); 192 previousMonth = month; 193 previousYear = year; 194 } 195 // Create the comic URL. 196 URL url = ComicURLFactory.createURL(ComicURLFactory.UCOMICS, comic, roller.getCurrentDate()); 197 // The output dir will have a subdir with the comic abbreviation and a subdir for each year, and month within that year. 198 // They will (of course) only be created if they didn't already exist. 199 File outputDir = new File(parent, comic + "/" + Integer.toString(year) + "/" + currentMonthString + "/"); 200 if(!outputDir.exists()) { 201 outputDir.mkdirs(); 202 } 203 // Retrieve the ComicImage. 204 ComicImage image = engine.grabComic(url); 205 // This is the outputfile proper. 206 File outputFile = new File(outputDir, image.getFilename()); 207 // See if the output file already exists. 208 // If it does, we shouldn't bother anymore; everything is updated. 209 if(outputFile.exists()) { 210 System.out.println("\n* Found comic '" + outputFile.getName() + "' in output path. Updating complete."); 211 break; 212 } 213 previousError = 0; 214 } catch(IOException ioe) { 215 System.err.println("Error for date " + roller.getFormattedCurrentDate("dd/MM/yyyy") + ": " + ioe.getMessage()); 216 previousError++; 217 totalError++; 218 } 219 roller.getPreviousDay(); 220 } 221 String last = roller.getFormattedCurrentDate("dd/MM/yyyy"); 222 if(previousError >= 14) { 223 System.out.println("\n\nExiting because the comic was not found for 15 consecutive days on the server."); 224 } else { 225 System.out.println("\n\nExiting because update was complete."); 226 } 227 System.out.println("\n - Last date: " + last + "\n - Total error count: " + totalError + "\n"); 228 } catch(Exception e) { 229 e.printStackTrace(); 230 } 231 } 232 } 233 234 /*** 235 * This method parses a three-letter code into the corresponding int as defined as a constant 236 * on the Calendar interface. 237 * 238 * @param aDayCode String with the three-letter day code 239 * @return int with the day code from the Calendar interface or '-1' if the three-letter 240 * code is not recognized. 241 */ 242 public static int parseDay(String aDayCode) { 243 int result = -1; 244 245 String code = aDayCode.trim().toLowerCase(); 246 247 if(code.equals("mon")) { 248 result = Calendar.MONDAY; 249 } else if(code.equals("tue")) { 250 result = Calendar.TUESDAY; 251 } else if(code.equals("wed")) { 252 result = Calendar.WEDNESDAY; 253 } else if(code.equals("thu")) { 254 result = Calendar.THURSDAY; 255 } else if(code.equals("fri")) { 256 result = Calendar.FRIDAY; 257 } else if(code.equals("sat")) { 258 result = Calendar.SATURDAY; 259 } else if(code.equals("sun")) { 260 result = Calendar.SUNDAY; 261 } 262 263 return result; 264 } 265 }

This page was automatically generated by Maven