Update nikiroo-utils, update Library
[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
9import be.nikiroo.fanfix.Instance;
10import be.nikiroo.fanfix.Library;
d0114000 11import be.nikiroo.fanfix.bundles.Config;
c1873e56
NR
12import be.nikiroo.fanfix.bundles.UiConfig;
13import be.nikiroo.fanfix.data.MetaData;
89cb07a6
NR
14import be.nikiroo.fanfix.data.Story;
15import be.nikiroo.fanfix.supported.BasicSupport;
3b2b638f 16import be.nikiroo.utils.Progress;
c1873e56 17import be.nikiroo.utils.ui.UIUtils;
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,
9119671d
NR
35
36 ;
37
38 public String getTypeName() {
39 String pkg = "be.nikiroo.fanfix.reader.";
40 switch (this) {
41 case CLI: return pkg + "CliReader";
42 case TUI: return pkg + "TuiReader";
43 case GUI: return pkg + "LocalReader";
44 }
45
46 return null;
47 }
3727aae2
NR
48 }
49
c1873e56 50 private static ReaderType defaultType = ReaderType.GUI;
89cb07a6 51 private Story story;
3727aae2
NR
52 private ReaderType type;
53
d0114000
NR
54 /**
55 * Take the default reader type configuration from the config file.
56 */
3727aae2 57 static {
d0114000
NR
58 String typeString = Instance.getConfig().getString(Config.READER_TYPE);
59 if (typeString != null && !typeString.isEmpty()) {
60 try {
61 ReaderType type = ReaderType.valueOf(typeString.toUpperCase());
62 defaultType = type;
63 } catch (IllegalArgumentException e) {
64 // Do nothing
65 }
66 }
3727aae2
NR
67 }
68
69 /**
70 * The type of this reader.
71 *
72 * @return the type
73 */
74 public ReaderType getType() {
75 return type;
76 }
77
78 /**
79 * The type of this reader.
80 *
81 * @param type
82 * the new type
83 */
84 protected BasicReader setType(ReaderType type) {
85 this.type = type;
86 return this;
87 }
89cb07a6
NR
88
89 /**
90 * Return the current {@link Story}.
91 *
92 * @return the {@link Story}
93 */
94 public Story getStory() {
95 return story;
96 }
97
98 /**
3727aae2 99 * Create a new {@link BasicReader} for a {@link Story} in the
89cb07a6
NR
100 * {@link Library} .
101 *
102 * @param luid
103 * the {@link Story} ID
92fb0719
NR
104 * @param pg
105 * the optional progress reporter
106 *
89cb07a6
NR
107 * @throws IOException
108 * in case of I/O error
109 */
92fb0719
NR
110 public void setStory(String luid, Progress pg) throws IOException {
111 story = Instance.getLibrary().getStory(luid, pg);
89cb07a6 112 if (story == null) {
92fb0719 113 throw new IOException("Cannot retrieve story from library: " + luid);
89cb07a6
NR
114 }
115 }
116
117 /**
3727aae2 118 * Create a new {@link BasicReader} for an external {@link Story}.
89cb07a6
NR
119 *
120 * @param source
121 * the {@link Story} {@link URL}
92fb0719
NR
122 * @param pg
123 * the optional progress reporter
124 *
89cb07a6
NR
125 * @throws IOException
126 * in case of I/O error
127 */
92fb0719 128 public void setStory(URL source, Progress pg) throws IOException {
89cb07a6
NR
129 BasicSupport support = BasicSupport.getSupport(source);
130 if (support == null) {
131 throw new IOException("URL not supported: " + source.toString());
132 }
133
92fb0719 134 story = support.process(source, pg);
89cb07a6
NR
135 if (story == null) {
136 throw new IOException(
137 "Cannot retrieve story from external source: "
138 + source.toString());
139
140 }
141 }
142
143 /**
144 * Start the {@link Story} Reading.
145 *
146 * @throws IOException
147 * in case of I/O error or if the {@link Story} was not
148 * previously set
149 */
150 public abstract void read() throws IOException;
151
152 /**
153 * Read the selected chapter (starting at 1).
154 *
155 * @param chapter
156 * the chapter
edd46289
NR
157 *
158 * @throws IOException
159 * in case of I/O error or if the {@link Story} was not
160 * previously set
89cb07a6 161 */
edd46289 162 public abstract void read(int chapter) throws IOException;
89cb07a6
NR
163
164 /**
165 * Start the reader in browse mode for the given type (or pass NULL for all
166 * types).
167 *
168 * @param type
169 * the type of {@link Story} to take into account, or NULL for
170 * all
171 */
333f0e7b 172 public abstract void start(String type);
3727aae2
NR
173
174 /**
d0114000
NR
175 * Return a new {@link BasicReader} ready for use if one is configured.
176 * <p>
177 * Can return NULL if none are configured.
3727aae2 178 *
d0114000 179 * @return a {@link BasicReader}, or NULL if none configured
3727aae2
NR
180 */
181 public static BasicReader getReader() {
333f0e7b
NR
182 try {
183 if (defaultType != null) {
9119671d
NR
184 return ((BasicReader)SerialUtils.createObject
185 (defaultType.getTypeName())).setType(defaultType);
d0114000 186 }
9119671d 187 } catch (Exception e) {
333f0e7b 188 Instance.syserr(new Exception("Cannot create a reader of type: "
9119671d 189 + defaultType + " (Not compiled in?)", e));
3727aae2
NR
190 }
191
192 return null;
193 }
194
195 /**
196 * The default {@link ReaderType} used when calling
197 * {@link BasicReader#getReader()}.
198 *
199 * @return the default type
200 */
201 public static ReaderType getDefaultReaderType() {
202 return defaultType;
203 }
204
205 /**
206 * The default {@link ReaderType} used when calling
207 * {@link BasicReader#getReader()}.
208 *
209 * @param defaultType
210 * the new default type
211 */
212 public static void setDefaultReaderType(ReaderType defaultType) {
213 BasicReader.defaultType = defaultType;
214 }
3b2b638f
NR
215
216 /**
217 * Return an {@link URL} from this {@link String}, be it a file path or an
218 * actual {@link URL}.
219 *
220 * @param sourceString
221 * the source
222 *
223 * @return the corresponding {@link URL}
224 *
225 * @throws MalformedURLException
226 * if this is neither a file nor a conventional {@link URL}
227 */
228 public static URL getUrl(String sourceString) throws MalformedURLException {
229 if (sourceString == null || sourceString.isEmpty()) {
230 throw new MalformedURLException("Empty url");
231 }
232
233 URL source = null;
234 try {
235 source = new URL(sourceString);
236 } catch (MalformedURLException e) {
237 File sourceFile = new File(sourceString);
238 source = sourceFile.toURI().toURL();
239 }
240
241 return source;
242 }
c1873e56
NR
243
244 // open with external player the related file
245 public static void open(String luid) throws IOException {
246 MetaData meta = Instance.getLibrary().getInfo(luid);
247 File target = Instance.getLibrary().getFile(luid);
248
249 open(meta, target);
250 }
251
252 // open with external player the related file
253 protected static void open(MetaData meta, File target) throws IOException {
254 String program = null;
255 if (meta.isImageDocument()) {
256 program = Instance.getUiConfig().getString(
257 UiConfig.IMAGES_DOCUMENT_READER);
258 } else {
259 program = Instance.getUiConfig().getString(
260 UiConfig.NON_IMAGES_DOCUMENT_READER);
261 }
262
263 if (program != null && program.trim().isEmpty()) {
264 program = null;
265 }
266
267 if (program == null) {
268 try {
269 Desktop.getDesktop().browse(target.toURI());
270 } catch (UnsupportedOperationException e) {
271 Runtime.getRuntime().exec(
272 new String[] { "xdg-open", target.getAbsolutePath() });
273
274 }
275 } else {
276 Runtime.getRuntime().exec(
277 new String[] { program, target.getAbsolutePath() });
278 }
279 }
89cb07a6 280}