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