1 package be
.nikiroo
.fanfix
;
4 import java
.io
.IOException
;
5 import java
.net
.MalformedURLException
;
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
.BasicReader
;
14 import be
.nikiroo
.fanfix
.supported
.BasicSupport
;
15 import be
.nikiroo
.fanfix
.supported
.BasicSupport
.SupportType
;
18 * Main program entry point.
24 * Main program entry point.
26 * Known environment variables:
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>
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>
46 public static void main(String
[] args
) {
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]);
55 } else if (action
.equals("--export")) {
56 if (args
.length
> 3) {
57 exitCode
= export(args
[1], args
[2], args
[3]);
59 } else if (action
.equals("--convert")) {
60 if (args
.length
> 3) {
65 args
.length
> 4 ? args
[4].toLowerCase().equals(
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,
75 } else if (action
.equals("--read")) {
76 if (args
.length
> 1) {
77 exitCode
= read(args
[1], args
.length
> 2 ? args
[2] : null,
83 if (exitCode
== 255) {
88 System
.exit(exitCode
);
93 * Return an {@link URL} from this {@link String}, be it a file path or an
99 * @return the corresponding {@link URL}
101 * @throws MalformedURLException
102 * if this is neither a file nor a conventional {@link URL}
104 private static URL
getUrl(String sourceString
) throws MalformedURLException
{
105 if (sourceString
== null || sourceString
.isEmpty()) {
106 throw new MalformedURLException("Empty url");
111 source
= new URL(sourceString
);
112 } catch (MalformedURLException e
) {
113 File sourceFile
= new File(sourceString
);
114 source
= sourceFile
.toURI().toURL();
121 * Import the given resource into the {@link Library}.
123 * @param sourceString
124 * the resource to import
126 * @return the exit return code (0 = success)
128 private static int imprt(String sourceString
) {
130 Story story
= Instance
.getLibrary().imprt(getUrl(sourceString
));
131 System
.out
.println(story
.getMeta().getLuid() + ": \""
132 + story
.getMeta().getTitle() + "\" imported.");
133 } catch (IOException e
) {
142 * Export the {@link Story} from the {@link Library} to the given target.
144 * @param sourceString
147 * the {@link OutputType} to use
151 * @return the exit return code (0 = success)
153 private static int export(String sourceString
, String typeString
,
155 OutputType type
= OutputType
.valueOfNullOkUC(typeString
);
157 Instance
.syserr(new Exception(trans(StringId
.OUTPUT_DESC
,
163 Story story
= Instance
.getLibrary().imprt(new URL(sourceString
));
164 Instance
.getLibrary().export(story
.getMeta().getLuid(), type
,
166 } catch (IOException e
) {
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).
179 * the {@link SupportType} to list the known stories of, or NULL
180 * to list all stories
182 * @return the exit return code (0 = success)
184 private static int list(String typeString
) {
185 SupportType type
= null;
187 type
= SupportType
.valueOfNullOkUC(typeString
);
188 } catch (Exception e
) {
189 Instance
.syserr(new Exception(
190 trans(StringId
.INPUT_DESC
, typeString
), e
));
194 BasicReader
.getReader().start(type
);
200 * Start the CLI reader for this {@link Story}.
203 * the LUID of the {@link Story} in the {@link Library} <b>or</b>
204 * the {@link Story} {@link URL}
206 * which {@link Chapter} to read (starting at 1), or NULL to get
207 * the {@link Story} description
209 * TRUE if the source is the {@link Story} LUID, FALSE if it is a
212 * @return the exit return code (0 = success)
214 private static int read(String story
, String chap
, boolean library
) {
216 BasicReader reader
= BasicReader
.getReader();
218 reader
.setStory(story
);
220 reader
.setStory(getUrl(story
));
224 reader
.read(Integer
.parseInt(chap
));
228 } catch (IOException e
) {
237 * Convert the {@link Story} into another format.
239 * @param sourceString
240 * the source {@link Story} to convert
242 * the {@link OutputType} to convert to
246 * TRUE to also export the cover and info file, even if the given
247 * {@link OutputType} does not usually save them
249 * @return the exit return code (0 = success)
251 private static int convert(String sourceString
, String typeString
,
252 String filename
, boolean infoCover
) {
255 String sourceName
= sourceString
;
257 URL source
= getUrl(sourceString
);
258 sourceName
= source
.toString();
259 if (source
.toString().startsWith("file://")) {
260 sourceName
= sourceName
.substring("file://".length());
263 OutputType type
= OutputType
.valueOfAllOkUC(typeString
);
265 Instance
.syserr(new IOException(trans(
266 StringId
.ERR_BAD_OUTPUT_TYPE
, typeString
)));
271 BasicSupport support
= BasicSupport
.getSupport(source
);
272 if (support
!= null) {
273 Story story
= support
.process(source
);
276 filename
= new File(filename
).getAbsolutePath();
277 BasicOutput
.getOutput(type
, infoCover
).process(
279 } catch (IOException e
) {
280 Instance
.syserr(new IOException(trans(
281 StringId
.ERR_SAVING
, filename
), e
));
285 Instance
.syserr(new IOException(trans(
286 StringId
.ERR_NOT_SUPPORTED
, source
)));
290 } catch (IOException e
) {
291 Instance
.syserr(new IOException(trans(StringId
.ERR_LOADING
,
296 } catch (MalformedURLException e
) {
297 Instance
.syserr(new IOException(trans(StringId
.ERR_BAD_URL
,
306 * Simple shortcut method to call {link Instance#getTrans()#getString()}.
309 * the ID to translate
311 * @return the translated result
313 private static String
trans(StringId id
, Object
... params
) {
314 return Instance
.getTrans().getString(id
, params
);
318 * Display the correct syntax of the program to the user.
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(),
325 builder
.append('\n');
328 String typesIn
= builder
.toString();
329 builder
.setLength(0);
331 for (OutputType type
: OutputType
.values()) {
332 builder
.append(trans(StringId
.ERR_SYNTAX_TYPE
, type
.toString(),
334 builder
.append('\n');
337 String typesOut
= builder
.toString();
339 System
.err
.println(trans(StringId
.ERR_SYNTAX
, typesIn
, typesOut
));