Commit | Line | Data |
---|---|---|
08fe2e33 NR |
1 | package be.nikiroo.fanfix; |
2 | ||
3 | import java.io.File; | |
4 | import java.io.IOException; | |
5 | import java.net.MalformedURLException; | |
6 | import java.net.URL; | |
7 | ||
8 | import be.nikiroo.fanfix.bundles.StringId; | |
9 | import be.nikiroo.fanfix.data.Chapter; | |
10 | import be.nikiroo.fanfix.data.Story; | |
11 | import be.nikiroo.fanfix.output.BasicOutput; | |
12 | import be.nikiroo.fanfix.output.BasicOutput.OutputType; | |
13 | import be.nikiroo.fanfix.reader.CliReader; | |
14 | import be.nikiroo.fanfix.supported.BasicSupport; | |
15 | import be.nikiroo.fanfix.supported.BasicSupport.SupportType; | |
16 | ||
17 | /** | |
18 | * Main program entry point. | |
19 | * | |
20 | * @author niki | |
21 | */ | |
22 | public class Main { | |
23 | /** | |
24 | * Main program entry point. | |
25 | * <p> | |
26 | * Known environment variables: | |
27 | * <ul> | |
28 | * <li>NOUTF: if set to 1, the program will prefer non-unicode | |
29 | * {@link String}s when possible</li> | |
30 | * <li>CONFIG_DIR: a path where to look for the <tt>.properties</tt> files | |
31 | * before taking the included ones; they will also be saved/updated into | |
32 | * this path when the program starts</li> | |
33 | * </ul> | |
34 | * | |
35 | * @param args | |
36 | * <ol> | |
37 | * <li>--import [URL]: import into library</li> <li>--export [id] | |
38 | * [output_type] [target]: export story to target</li> <li> | |
39 | * --convert [URL] [output_type] [target]: convert URL into | |
40 | * target</li> <li>--read [id]: read the given story from the | |
41 | * library</li> <li>--read-url [URL]: convert on the fly and read | |
42 | * the story, without saving it</li> <li>--list: list the stories | |
43 | * present in the library</li> | |
44 | * </ol> | |
45 | */ | |
46 | public static void main(String[] args) { | |
47 | int exitCode = 255; | |
48 | ||
49 | if (args.length > 0) { | |
50 | String action = args[0]; | |
51 | if (action.equals("--import")) { | |
52 | if (args.length > 1) { | |
53 | exitCode = imprt(args[1]); | |
54 | } | |
55 | } else if (action.equals("--export")) { | |
56 | if (args.length > 3) { | |
57 | exitCode = export(args[1], args[2], args[3]); | |
58 | } | |
59 | } else if (action.equals("--convert")) { | |
60 | if (args.length > 3) { | |
61 | exitCode = convert( | |
62 | args[1], | |
63 | args[2], | |
64 | args[3], | |
65 | args.length > 4 ? args[4].toLowerCase().equals( | |
66 | "+info") : false); | |
67 | } | |
68 | } else if (action.equals("--list")) { | |
69 | exitCode = list(args.length > 1 ? args[1] : null); | |
70 | } else if (action.equals("--read-url")) { | |
71 | if (args.length > 1) { | |
72 | exitCode = read(args[1], args.length > 2 ? args[2] : null, | |
73 | false); | |
74 | } | |
75 | } else if (action.equals("--read")) { | |
76 | if (args.length > 1) { | |
77 | exitCode = read(args[1], args.length > 2 ? args[2] : null, | |
78 | true); | |
79 | } | |
80 | } | |
81 | } | |
82 | ||
83 | if (exitCode == 255) { | |
84 | syntax(); | |
85 | } | |
86 | ||
87 | if (exitCode != 0) { | |
88 | System.exit(exitCode); | |
89 | } | |
90 | } | |
91 | ||
92 | /** | |
93 | * Return an {@link URL} from this {@link String}, be it a file path or an | |
94 | * actual {@link URL}. | |
95 | * | |
96 | * @param sourceString | |
97 | * the source | |
98 | * | |
99 | * @return the corresponding {@link URL} | |
100 | * | |
101 | * @throws MalformedURLException | |
102 | * if this is neither a file nor a conventional {@link URL} | |
103 | */ | |
104 | private static URL getUrl(String sourceString) throws MalformedURLException { | |
105 | if (sourceString == null || sourceString.isEmpty()) { | |
106 | throw new MalformedURLException("Empty url"); | |
107 | } | |
108 | ||
109 | URL source = null; | |
110 | try { | |
111 | source = new URL(sourceString); | |
112 | } catch (MalformedURLException e) { | |
113 | File sourceFile = new File(sourceString); | |
114 | source = sourceFile.toURI().toURL(); | |
115 | } | |
116 | ||
117 | return source; | |
118 | } | |
119 | ||
120 | /** | |
121 | * Import the given resource into the {@link Library}. | |
122 | * | |
123 | * @param sourceString | |
124 | * the resource to import | |
125 | * | |
126 | * @return the exit return code (0 = success) | |
127 | */ | |
128 | private static int imprt(String sourceString) { | |
129 | try { | |
130 | Story story = Instance.getLibrary().imprt(getUrl(sourceString)); | |
131 | System.out.println(story.getMeta().getLuid() + ": \"" | |
132 | + story.getMeta().getTitle() + "\" imported."); | |
133 | } catch (IOException e) { | |
134 | Instance.syserr(e); | |
135 | return 1; | |
136 | } | |
137 | ||
138 | return 0; | |
139 | } | |
140 | ||
141 | /** | |
142 | * Export the {@link Story} from the {@link Library} to the given target. | |
143 | * | |
144 | * @param sourceString | |
145 | * the story LUID | |
146 | * @param typeString | |
147 | * the {@link OutputType} to use | |
148 | * @param target | |
149 | * the target | |
150 | * | |
151 | * @return the exit return code (0 = success) | |
152 | */ | |
153 | private static int export(String sourceString, String typeString, | |
154 | String target) { | |
155 | OutputType type = OutputType.valueOfNullOkUC(typeString); | |
156 | if (type == null) { | |
157 | Instance.syserr(new Exception(trans(StringId.OUTPUT_DESC, | |
158 | typeString))); | |
159 | return 1; | |
160 | } | |
161 | ||
162 | try { | |
163 | Story story = Instance.getLibrary().imprt(new URL(sourceString)); | |
164 | Instance.getLibrary().export(story.getMeta().getLuid(), type, | |
165 | target); | |
166 | } catch (IOException e) { | |
167 | Instance.syserr(e); | |
168 | return 4; | |
169 | } | |
170 | ||
171 | return 0; | |
172 | } | |
173 | ||
174 | /** | |
175 | * List the stories of the given type from the {@link Library} (unless NULL | |
176 | * is passed, in which case all stories will be listed). | |
177 | * | |
178 | * @param typeString | |
179 | * the {@link SupportType} to list the known stories of, or NULL | |
180 | * to list all stories | |
181 | * | |
182 | * @return the exit return code (0 = success) | |
183 | */ | |
184 | private static int list(String typeString) { | |
185 | SupportType type = null; | |
186 | try { | |
187 | type = SupportType.valueOfNullOkUC(typeString); | |
188 | } catch (Exception e) { | |
189 | Instance.syserr(new Exception( | |
190 | trans(StringId.INPUT_DESC, typeString), e)); | |
191 | return 1; | |
192 | } | |
193 | ||
194 | CliReader.list(type); | |
195 | ||
196 | return 0; | |
197 | } | |
198 | ||
199 | /** | |
200 | * Start the CLI reader for this {@link Story}. | |
201 | * | |
202 | * @param story | |
203 | * the LUID of the {@link Story} in the {@link Library} <b>or</b> | |
204 | * the {@link Story} {@link URL} | |
205 | * @param chap | |
206 | * which {@link Chapter} to read (starting at 1), or NULL to get | |
207 | * the {@link Story} description | |
208 | * @param library | |
209 | * TRUE if the source is the {@link Story} LUID, FALSE if it is a | |
210 | * {@link URL} | |
211 | * | |
212 | * @return the exit return code (0 = success) | |
213 | */ | |
214 | private static int read(String story, String chap, boolean library) { | |
215 | try { | |
216 | CliReader reader; | |
217 | if (library) { | |
218 | reader = new CliReader(story); | |
219 | } else { | |
220 | reader = new CliReader(getUrl(story)); | |
221 | } | |
222 | ||
223 | if (chap != null) { | |
224 | reader.read(Integer.parseInt(chap)); | |
225 | } else { | |
226 | reader.read(); | |
227 | } | |
228 | } catch (IOException e) { | |
229 | Instance.syserr(e); | |
230 | return 1; | |
231 | } | |
232 | ||
233 | return 0; | |
234 | } | |
235 | ||
236 | /** | |
237 | * Convert the {@link Story} into another format. | |
238 | * | |
239 | * @param sourceString | |
240 | * the source {@link Story} to convert | |
241 | * @param typeString | |
242 | * the {@link OutputType} to convert to | |
243 | * @param filename | |
244 | * the target file | |
245 | * @param infoCover | |
246 | * TRUE to also export the cover and info file, even if the given | |
247 | * {@link OutputType} does not usually save them | |
248 | * | |
249 | * @return the exit return code (0 = success) | |
250 | */ | |
251 | private static int convert(String sourceString, String typeString, | |
252 | String filename, boolean infoCover) { | |
253 | int exitCode = 0; | |
254 | ||
255 | String sourceName = sourceString; | |
256 | try { | |
257 | URL source = getUrl(sourceString); | |
258 | sourceName = source.toString(); | |
259 | if (source.toString().startsWith("file://")) { | |
260 | sourceName = sourceName.substring("file://".length()); | |
261 | } | |
262 | ||
263 | OutputType type = OutputType.valueOfAllOkUC(typeString); | |
264 | if (type == null) { | |
265 | Instance.syserr(new IOException(trans( | |
266 | StringId.ERR_BAD_OUTPUT_TYPE, typeString))); | |
267 | ||
268 | exitCode = 2; | |
269 | } else { | |
270 | try { | |
271 | BasicSupport support = BasicSupport.getSupport(source); | |
272 | if (support != null) { | |
273 | Story story = support.process(source); | |
274 | ||
275 | try { | |
276 | filename = new File(filename).getAbsolutePath(); | |
277 | BasicOutput.getOutput(type, infoCover).process( | |
278 | story, filename); | |
279 | } catch (IOException e) { | |
280 | Instance.syserr(new IOException(trans( | |
281 | StringId.ERR_SAVING, filename), e)); | |
282 | exitCode = 5; | |
283 | } | |
284 | } else { | |
285 | Instance.syserr(new IOException(trans( | |
286 | StringId.ERR_NOT_SUPPORTED, source))); | |
287 | ||
288 | exitCode = 4; | |
289 | } | |
290 | } catch (IOException e) { | |
291 | Instance.syserr(new IOException(trans(StringId.ERR_LOADING, | |
292 | sourceName), e)); | |
293 | exitCode = 3; | |
294 | } | |
295 | } | |
296 | } catch (MalformedURLException e) { | |
297 | Instance.syserr(new IOException(trans(StringId.ERR_BAD_URL, | |
298 | sourceName), e)); | |
299 | exitCode = 1; | |
300 | } | |
301 | ||
302 | return exitCode; | |
303 | } | |
304 | ||
305 | /** | |
306 | * Simple shortcut method to call {link Instance#getTrans()#getString()}. | |
307 | * | |
308 | * @param id | |
309 | * the ID to translate | |
310 | * | |
311 | * @return the translated result | |
312 | */ | |
313 | private static String trans(StringId id, Object... params) { | |
314 | return Instance.getTrans().getString(id, params); | |
315 | } | |
316 | ||
317 | /** | |
318 | * Display the correct syntax of the program to the user. | |
319 | */ | |
320 | private static void syntax() { | |
321 | StringBuilder builder = new StringBuilder(); | |
322 | for (SupportType type : SupportType.values()) { | |
323 | builder.append(trans(StringId.ERR_SYNTAX_TYPE, type.toString(), | |
324 | type.getDesc())); | |
325 | builder.append('\n'); | |
326 | } | |
327 | ||
328 | String typesIn = builder.toString(); | |
329 | builder.setLength(0); | |
330 | ||
331 | for (OutputType type : OutputType.values()) { | |
332 | builder.append(trans(StringId.ERR_SYNTAX_TYPE, type.toString(), | |
333 | type.getDesc())); | |
334 | builder.append('\n'); | |
335 | } | |
336 | ||
337 | String typesOut = builder.toString(); | |
338 | ||
339 | System.err.println(trans(StringId.ERR_SYNTAX, typesIn, typesOut)); | |
340 | } | |
341 | } |