Code cleanup 3 and update jexer-niki :
[fanfix.git] / src / be / nikiroo / fanfix / reader / BasicReader.java
1 package be.nikiroo.fanfix.reader;
2
3 import java.awt.Desktop;
4 import java.io.File;
5 import java.io.IOException;
6 import java.net.MalformedURLException;
7 import java.net.URL;
8
9 import be.nikiroo.fanfix.Instance;
10 import be.nikiroo.fanfix.bundles.Config;
11 import be.nikiroo.fanfix.bundles.UiConfig;
12 import be.nikiroo.fanfix.data.MetaData;
13 import be.nikiroo.fanfix.data.Story;
14 import be.nikiroo.fanfix.library.BasicLibrary;
15 import be.nikiroo.fanfix.library.LocalLibrary;
16 import be.nikiroo.fanfix.supported.BasicSupport;
17 import be.nikiroo.utils.Progress;
18 import be.nikiroo.utils.serial.SerialUtils;
19
20 /**
21 * The class that handles the different {@link Story} readers you can use.
22 * <p>
23 * All the readers should be accessed via {@link BasicReader#getReader()}.
24 *
25 * @author niki
26 */
27 public abstract class BasicReader implements Reader {
28 private static BasicLibrary defaultLibrary = Instance.getLibrary();
29 private static ReaderType defaultType = ReaderType.GUI;
30
31 private BasicLibrary lib;
32 private MetaData meta;
33 private Story story;
34 private int chapter;
35
36 /**
37 * Take the default reader type configuration from the config file.
38 */
39 static {
40 String typeString = Instance.getConfig().getString(Config.READER_TYPE);
41 if (typeString != null && !typeString.isEmpty()) {
42 try {
43 ReaderType type = ReaderType.valueOf(typeString.toUpperCase());
44 defaultType = type;
45 } catch (IllegalArgumentException e) {
46 // Do nothing
47 }
48 }
49 }
50
51 public synchronized Story getStory(Progress pg) {
52 if (story == null) {
53 story = getLibrary().getStory(meta.getLuid(), pg);
54 }
55
56 return story;
57 }
58
59 public BasicLibrary getLibrary() {
60 if (lib == null) {
61 lib = defaultLibrary;
62 }
63
64 return lib;
65 }
66
67 public void setLibrary(BasicLibrary lib) {
68 this.lib = lib;
69 }
70
71 public MetaData getMeta() {
72 return meta;
73 }
74
75 public synchronized void setMeta(MetaData meta) throws IOException {
76 setMeta(meta == null ? null : meta.getLuid()); // must check the library
77 }
78
79 public synchronized void setMeta(String luid) throws IOException {
80 story = null;
81 meta = getLibrary().getInfo(luid);
82
83 if (meta == null) {
84 throw new IOException("Cannot retrieve story from library: " + luid);
85 }
86 }
87
88 public synchronized void setMeta(URL source, Progress pg)
89 throws IOException {
90 BasicSupport support = BasicSupport.getSupport(source);
91 if (support == null) {
92 throw new IOException("URL not supported: " + source.toString());
93 }
94
95 story = support.process(source, pg);
96 if (story == null) {
97 throw new IOException(
98 "Cannot retrieve story from external source: "
99 + source.toString());
100 }
101
102 meta = story.getMeta();
103 }
104
105 public int getChapter() {
106 return chapter;
107 }
108
109 public void setChapter(int chapter) {
110 this.chapter = chapter;
111 }
112
113 /**
114 * Return a new {@link BasicReader} ready for use if one is configured.
115 * <p>
116 * Can return NULL if none are configured.
117 *
118 * @return a {@link BasicReader}, or NULL if none configured
119 */
120 public static Reader getReader() {
121 try {
122 if (defaultType != null) {
123 return (Reader) SerialUtils.createObject(defaultType
124 .getTypeName());
125 }
126 } catch (Exception e) {
127 Instance.syserr(new Exception("Cannot create a reader of type: "
128 + defaultType + " (Not compiled in?)", e));
129 }
130
131 return null;
132 }
133
134 /**
135 * The default {@link Reader.ReaderType} used when calling
136 * {@link BasicReader#getReader()}.
137 *
138 * @return the default type
139 */
140 public static ReaderType getDefaultReaderType() {
141 return defaultType;
142 }
143
144 /**
145 * The default {@link Reader.ReaderType} used when calling
146 * {@link BasicReader#getReader()}.
147 *
148 * @param defaultType
149 * the new default type
150 */
151 public static void setDefaultReaderType(ReaderType defaultType) {
152 BasicReader.defaultType = defaultType;
153 }
154
155 /**
156 * Change the default {@link LocalLibrary} to open with the
157 * {@link BasicReader}s.
158 *
159 * @param lib
160 * the new {@link LocalLibrary}
161 */
162 public static void setDefaultLibrary(BasicLibrary lib) {
163 BasicReader.defaultLibrary = lib;
164 }
165
166 /**
167 * Return an {@link URL} from this {@link String}, be it a file path or an
168 * actual {@link URL}.
169 *
170 * @param sourceString
171 * the source
172 *
173 * @return the corresponding {@link URL}
174 *
175 * @throws MalformedURLException
176 * if this is neither a file nor a conventional {@link URL}
177 */
178 public static URL getUrl(String sourceString) throws MalformedURLException {
179 if (sourceString == null || sourceString.isEmpty()) {
180 throw new MalformedURLException("Empty url");
181 }
182
183 URL source = null;
184 try {
185 source = new URL(sourceString);
186 } catch (MalformedURLException e) {
187 File sourceFile = new File(sourceString);
188 source = sourceFile.toURI().toURL();
189 }
190
191 return source;
192 }
193
194 /**
195 * Open the {@link Story} with an external reader (the program will be
196 * passed the main file associated with this {@link Story}).
197 *
198 * @param lib
199 * the {@link BasicLibrary} to select the {@link Story} from
200 * @param luid
201 * the {@link Story} LUID
202 *
203 * @throws IOException
204 * in case of I/O error
205 */
206 public static void openExternal(BasicLibrary lib, String luid)
207 throws IOException {
208 MetaData meta = lib.getInfo(luid);
209 File target = lib.getFile(luid);
210
211 openExternal(meta, target);
212 }
213
214 /**
215 * Open the {@link Story} with an external reader (the program will be
216 * passed the given target file).
217 *
218 * @param meta
219 * the {@link Story} to load
220 * @param target
221 * the target {@link File}
222 *
223 * @throws IOException
224 * in case of I/O error
225 */
226 protected static void openExternal(MetaData meta, File target)
227 throws IOException {
228 String program = null;
229 if (meta.isImageDocument()) {
230 program = Instance.getUiConfig().getString(
231 UiConfig.IMAGES_DOCUMENT_READER);
232 } else {
233 program = Instance.getUiConfig().getString(
234 UiConfig.NON_IMAGES_DOCUMENT_READER);
235 }
236
237 if (program != null && program.trim().isEmpty()) {
238 program = null;
239 }
240
241 if (program == null) {
242 try {
243 Desktop.getDesktop().browse(target.toURI());
244 } catch (UnsupportedOperationException e) {
245 Runtime.getRuntime().exec(
246 new String[] { "xdg-open", target.getAbsolutePath() });
247
248 }
249 } else {
250 Runtime.getRuntime().exec(
251 new String[] { program, target.getAbsolutePath() });
252 }
253 }
254 }