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