Add progress reporting on GUI
[fanfix.git] / src / be / nikiroo / fanfix / reader / BasicReader.java
1 package be.nikiroo.fanfix.reader;
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.Instance;
9 import be.nikiroo.fanfix.Library;
10 import be.nikiroo.fanfix.bundles.Config;
11 import be.nikiroo.fanfix.data.Story;
12 import be.nikiroo.fanfix.supported.BasicSupport;
13 import be.nikiroo.utils.Progress;
14
15 /**
16 * The class that handles the different {@link Story} readers you can use.
17 * <p>
18 * All the readers should be accessed via {@link BasicReader#getReader()}.
19 *
20 * @author niki
21 */
22 public abstract class BasicReader {
23 public enum ReaderType {
24 /** Simple reader that outputs everything on the console */
25 CLI,
26 /** Reader that starts local programs to handle the stories */
27 LOCAL
28 }
29
30 private static ReaderType defaultType = ReaderType.CLI;
31 private Story story;
32 private ReaderType type;
33
34 /**
35 * Take the default reader type configuration from the config file.
36 */
37 static {
38 String typeString = Instance.getConfig().getString(Config.READER_TYPE);
39 if (typeString != null && !typeString.isEmpty()) {
40 try {
41 ReaderType type = ReaderType.valueOf(typeString.toUpperCase());
42 defaultType = type;
43 } catch (IllegalArgumentException e) {
44 // Do nothing
45 }
46 }
47 }
48
49 /**
50 * The type of this reader.
51 *
52 * @return the type
53 */
54 public ReaderType getType() {
55 return type;
56 }
57
58 /**
59 * The type of this reader.
60 *
61 * @param type
62 * the new type
63 */
64 protected BasicReader setType(ReaderType type) {
65 this.type = type;
66 return this;
67 }
68
69 /**
70 * Return the current {@link Story}.
71 *
72 * @return the {@link Story}
73 */
74 public Story getStory() {
75 return story;
76 }
77
78 /**
79 * Create a new {@link BasicReader} for a {@link Story} in the
80 * {@link Library} .
81 *
82 * @param luid
83 * the {@link Story} ID
84 * @param pg
85 * the optional progress reporter
86 *
87 * @throws IOException
88 * in case of I/O error
89 */
90 public void setStory(String luid, Progress pg) throws IOException {
91 story = Instance.getLibrary().getStory(luid, pg);
92 if (story == null) {
93 throw new IOException("Cannot retrieve story from library: " + luid);
94 }
95 }
96
97 /**
98 * Create a new {@link BasicReader} for an external {@link Story}.
99 *
100 * @param source
101 * the {@link Story} {@link URL}
102 * @param pg
103 * the optional progress reporter
104 *
105 * @throws IOException
106 * in case of I/O error
107 */
108 public void setStory(URL source, Progress pg) throws IOException {
109 BasicSupport support = BasicSupport.getSupport(source);
110 if (support == null) {
111 throw new IOException("URL not supported: " + source.toString());
112 }
113
114 story = support.process(source, pg);
115 if (story == null) {
116 throw new IOException(
117 "Cannot retrieve story from external source: "
118 + source.toString());
119
120 }
121 }
122
123 /**
124 * Start the {@link Story} Reading.
125 *
126 * @throws IOException
127 * in case of I/O error or if the {@link Story} was not
128 * previously set
129 */
130 public abstract void read() throws IOException;
131
132 /**
133 * Read the selected chapter (starting at 1).
134 *
135 * @param chapter
136 * the chapter
137 */
138 public abstract void read(int chapter);
139
140 /**
141 * Start the reader in browse mode for the given type (or pass NULL for all
142 * types).
143 *
144 * @param type
145 * the type of {@link Story} to take into account, or NULL for
146 * all
147 */
148 public abstract void start(String type);
149
150 /**
151 * Return a new {@link BasicReader} ready for use if one is configured.
152 * <p>
153 * Can return NULL if none are configured.
154 *
155 * @return a {@link BasicReader}, or NULL if none configured
156 */
157 public static BasicReader getReader() {
158 try {
159 if (defaultType != null) {
160 switch (defaultType) {
161 case LOCAL:
162 return new LocalReader().setType(ReaderType.LOCAL);
163 case CLI:
164 return new CliReader().setType(ReaderType.CLI);
165 }
166 }
167 } catch (IOException e) {
168 Instance.syserr(new Exception("Cannot create a reader of type: "
169 + defaultType, e));
170 }
171
172 return null;
173 }
174
175 /**
176 * The default {@link ReaderType} used when calling
177 * {@link BasicReader#getReader()}.
178 *
179 * @return the default type
180 */
181 public static ReaderType getDefaultReaderType() {
182 return defaultType;
183 }
184
185 /**
186 * The default {@link ReaderType} used when calling
187 * {@link BasicReader#getReader()}.
188 *
189 * @param defaultType
190 * the new default type
191 */
192 public static void setDefaultReaderType(ReaderType defaultType) {
193 BasicReader.defaultType = defaultType;
194 }
195
196 /**
197 * Return an {@link URL} from this {@link String}, be it a file path or an
198 * actual {@link URL}.
199 *
200 * @param sourceString
201 * the source
202 *
203 * @return the corresponding {@link URL}
204 *
205 * @throws MalformedURLException
206 * if this is neither a file nor a conventional {@link URL}
207 */
208 public static URL getUrl(String sourceString) throws MalformedURLException {
209 if (sourceString == null || sourceString.isEmpty()) {
210 throw new MalformedURLException("Empty url");
211 }
212
213 URL source = null;
214 try {
215 source = new URL(sourceString);
216 } catch (MalformedURLException e) {
217 File sourceFile = new File(sourceString);
218 source = sourceFile.toURI().toURL();
219 }
220
221 return source;
222 }
223 }