Dependency fix + Local/Remote Library support
[fanfix.git] / src / be / nikiroo / fanfix / reader / BasicReader.java
CommitLineData
89cb07a6
NR
1package be.nikiroo.fanfix.reader;
2
c1873e56 3import java.awt.Desktop;
3b2b638f 4import java.io.File;
89cb07a6 5import java.io.IOException;
3b2b638f 6import java.net.MalformedURLException;
89cb07a6
NR
7import java.net.URL;
8
68e2c6d2 9import be.nikiroo.fanfix.BasicLibrary;
89cb07a6 10import be.nikiroo.fanfix.Instance;
68e2c6d2 11import be.nikiroo.fanfix.LocalLibrary;
d0114000 12import be.nikiroo.fanfix.bundles.Config;
c1873e56
NR
13import be.nikiroo.fanfix.bundles.UiConfig;
14import be.nikiroo.fanfix.data.MetaData;
89cb07a6
NR
15import be.nikiroo.fanfix.data.Story;
16import be.nikiroo.fanfix.supported.BasicSupport;
3b2b638f 17import be.nikiroo.utils.Progress;
9119671d 18import be.nikiroo.utils.serial.SerialUtils;
89cb07a6
NR
19
20/**
dd56a893 21 * The class that handles the different {@link Story} readers you can use.
89cb07a6 22 * <p>
dd56a893 23 * All the readers should be accessed via {@link BasicReader#getReader()}.
89cb07a6
NR
24 *
25 * @author niki
26 */
3727aae2
NR
27public abstract class BasicReader {
28 public enum ReaderType {
29 /** Simple reader that outputs everything on the console */
30 CLI,
31 /** Reader that starts local programs to handle the stories */
c1873e56
NR
32 GUI,
33 /** A text (UTF-8) reader with menu and text windows */
34 TUI,
b0e88ebd 35
9119671d 36 ;
b0e88ebd 37
9119671d
NR
38 public String getTypeName() {
39 String pkg = "be.nikiroo.fanfix.reader.";
40 switch (this) {
b0e88ebd
NR
41 case CLI:
42 return pkg + "CliReader";
43 case TUI:
44 return pkg + "TuiReader";
45 case GUI:
46 return pkg + "LocalReader";
9119671d 47 }
b0e88ebd 48
9119671d
NR
49 return null;
50 }
3727aae2
NR
51 }
52
68e2c6d2 53 private static BasicLibrary defaultLibrary = Instance.getLibrary();
c1873e56 54 private static ReaderType defaultType = ReaderType.GUI;
b0e88ebd 55
68e2c6d2 56 private BasicLibrary lib;
89cb07a6 57 private Story story;
3727aae2
NR
58 private ReaderType type;
59
d0114000
NR
60 /**
61 * Take the default reader type configuration from the config file.
62 */
3727aae2 63 static {
d0114000
NR
64 String typeString = Instance.getConfig().getString(Config.READER_TYPE);
65 if (typeString != null && !typeString.isEmpty()) {
66 try {
67 ReaderType type = ReaderType.valueOf(typeString.toUpperCase());
68 defaultType = type;
69 } catch (IllegalArgumentException e) {
70 // Do nothing
71 }
72 }
3727aae2
NR
73 }
74
75 /**
76 * The type of this reader.
77 *
78 * @return the type
79 */
80 public ReaderType getType() {
81 return type;
82 }
83
84 /**
85 * The type of this reader.
86 *
87 * @param type
88 * the new type
89 */
90 protected BasicReader setType(ReaderType type) {
91 this.type = type;
92 return this;
93 }
89cb07a6
NR
94
95 /**
96 * Return the current {@link Story}.
97 *
98 * @return the {@link Story}
99 */
100 public Story getStory() {
101 return story;
102 }
103
b0e88ebd 104 /**
68e2c6d2
NR
105 * The {@link LocalLibrary} to load the stories from (by default, takes the
106 * default {@link LocalLibrary}).
b0e88ebd 107 *
68e2c6d2 108 * @return the {@link LocalLibrary}
b0e88ebd 109 */
68e2c6d2 110 public BasicLibrary getLibrary() {
b0e88ebd
NR
111 if (lib == null) {
112 lib = defaultLibrary;
113 }
114
115 return lib;
116 }
117
118 /**
68e2c6d2 119 * Change the {@link LocalLibrary} that will be managed by this
b0e88ebd
NR
120 * {@link BasicReader}.
121 *
122 * @param lib
68e2c6d2 123 * the new {@link LocalLibrary}
b0e88ebd 124 */
68e2c6d2 125 public void setLibrary(LocalLibrary lib) {
b0e88ebd
NR
126 this.lib = lib;
127 }
128
89cb07a6 129 /**
3727aae2 130 * Create a new {@link BasicReader} for a {@link Story} in the
68e2c6d2 131 * {@link LocalLibrary}.
89cb07a6
NR
132 *
133 * @param luid
134 * the {@link Story} ID
92fb0719
NR
135 * @param pg
136 * the optional progress reporter
137 *
89cb07a6
NR
138 * @throws IOException
139 * in case of I/O error
140 */
92fb0719 141 public void setStory(String luid, Progress pg) throws IOException {
b0e88ebd 142 story = lib.getStory(luid, pg);
89cb07a6 143 if (story == null) {
92fb0719 144 throw new IOException("Cannot retrieve story from library: " + luid);
89cb07a6
NR
145 }
146 }
147
148 /**
3727aae2 149 * Create a new {@link BasicReader} for an external {@link Story}.
89cb07a6
NR
150 *
151 * @param source
152 * the {@link Story} {@link URL}
92fb0719
NR
153 * @param pg
154 * the optional progress reporter
155 *
89cb07a6
NR
156 * @throws IOException
157 * in case of I/O error
158 */
92fb0719 159 public void setStory(URL source, Progress pg) throws IOException {
89cb07a6
NR
160 BasicSupport support = BasicSupport.getSupport(source);
161 if (support == null) {
162 throw new IOException("URL not supported: " + source.toString());
163 }
164
92fb0719 165 story = support.process(source, pg);
89cb07a6
NR
166 if (story == null) {
167 throw new IOException(
168 "Cannot retrieve story from external source: "
169 + source.toString());
170
171 }
172 }
173
174 /**
175 * Start the {@link Story} Reading.
176 *
177 * @throws IOException
178 * in case of I/O error or if the {@link Story} was not
179 * previously set
180 */
181 public abstract void read() throws IOException;
182
183 /**
184 * Read the selected chapter (starting at 1).
185 *
186 * @param chapter
187 * the chapter
edd46289
NR
188 *
189 * @throws IOException
190 * in case of I/O error or if the {@link Story} was not
191 * previously set
89cb07a6 192 */
edd46289 193 public abstract void read(int chapter) throws IOException;
89cb07a6
NR
194
195 /**
b0e88ebd
NR
196 * Start the reader in browse mode for the given source (or pass NULL for
197 * all sources).
89cb07a6 198 *
b0e88ebd
NR
199 * @param library
200 * the library to browse
201 *
202 * @param source
89cb07a6
NR
203 * the type of {@link Story} to take into account, or NULL for
204 * all
205 */
b0e88ebd 206 public abstract void browse(String source);
3727aae2
NR
207
208 /**
d0114000
NR
209 * Return a new {@link BasicReader} ready for use if one is configured.
210 * <p>
211 * Can return NULL if none are configured.
3727aae2 212 *
d0114000 213 * @return a {@link BasicReader}, or NULL if none configured
3727aae2
NR
214 */
215 public static BasicReader getReader() {
333f0e7b
NR
216 try {
217 if (defaultType != null) {
b0e88ebd
NR
218 return ((BasicReader) SerialUtils.createObject(defaultType
219 .getTypeName())).setType(defaultType);
d0114000 220 }
9119671d 221 } catch (Exception e) {
333f0e7b 222 Instance.syserr(new Exception("Cannot create a reader of type: "
9119671d 223 + defaultType + " (Not compiled in?)", e));
3727aae2
NR
224 }
225
226 return null;
227 }
228
229 /**
230 * The default {@link ReaderType} used when calling
231 * {@link BasicReader#getReader()}.
232 *
233 * @return the default type
234 */
235 public static ReaderType getDefaultReaderType() {
236 return defaultType;
237 }
238
239 /**
240 * The default {@link ReaderType} used when calling
241 * {@link BasicReader#getReader()}.
242 *
243 * @param defaultType
244 * the new default type
245 */
246 public static void setDefaultReaderType(ReaderType defaultType) {
247 BasicReader.defaultType = defaultType;
248 }
3b2b638f 249
b0e88ebd 250 /**
68e2c6d2
NR
251 * Change the default {@link LocalLibrary} to open with the
252 * {@link BasicReader}s.
b0e88ebd
NR
253 *
254 * @param lib
68e2c6d2 255 * the new {@link LocalLibrary}
b0e88ebd 256 */
68e2c6d2 257 public static void setDefaultLibrary(BasicLibrary lib) {
b0e88ebd
NR
258 BasicReader.defaultLibrary = lib;
259 }
260
3b2b638f
NR
261 /**
262 * Return an {@link URL} from this {@link String}, be it a file path or an
263 * actual {@link URL}.
264 *
265 * @param sourceString
266 * the source
267 *
268 * @return the corresponding {@link URL}
269 *
270 * @throws MalformedURLException
271 * if this is neither a file nor a conventional {@link URL}
272 */
273 public static URL getUrl(String sourceString) throws MalformedURLException {
274 if (sourceString == null || sourceString.isEmpty()) {
275 throw new MalformedURLException("Empty url");
276 }
277
278 URL source = null;
279 try {
280 source = new URL(sourceString);
281 } catch (MalformedURLException e) {
282 File sourceFile = new File(sourceString);
283 source = sourceFile.toURI().toURL();
284 }
285
286 return source;
287 }
c1873e56
NR
288
289 // open with external player the related file
68e2c6d2 290 public static void open(BasicLibrary lib, String luid) throws IOException {
b0e88ebd
NR
291 MetaData meta = lib.getInfo(luid);
292 File target = lib.getFile(luid);
c1873e56
NR
293
294 open(meta, target);
295 }
296
297 // open with external player the related file
298 protected static void open(MetaData meta, File target) throws IOException {
299 String program = null;
300 if (meta.isImageDocument()) {
301 program = Instance.getUiConfig().getString(
302 UiConfig.IMAGES_DOCUMENT_READER);
303 } else {
304 program = Instance.getUiConfig().getString(
305 UiConfig.NON_IMAGES_DOCUMENT_READER);
306 }
307
308 if (program != null && program.trim().isEmpty()) {
309 program = null;
310 }
311
312 if (program == null) {
313 try {
314 Desktop.getDesktop().browse(target.toURI());
315 } catch (UnsupportedOperationException e) {
316 Runtime.getRuntime().exec(
317 new String[] { "xdg-open", target.getAbsolutePath() });
318
319 }
320 } else {
321 Runtime.getRuntime().exec(
322 new String[] { program, target.getAbsolutePath() });
323 }
324 }
89cb07a6 325}