Merge branch 'master' into subtree
[nikiroo-utils.git] / reader / BasicReader.java
CommitLineData
89cb07a6
NR
1package be.nikiroo.fanfix.reader;
2
3b2b638f 3import java.io.File;
89cb07a6 4import java.io.IOException;
3b2b638f 5import java.net.MalformedURLException;
89cb07a6 6import java.net.URL;
df6e2d88
NR
7import java.text.ParseException;
8import java.text.SimpleDateFormat;
df6e2d88 9import java.util.Date;
a6c830bb
NR
10import java.util.Map;
11import java.util.TreeMap;
89cb07a6
NR
12
13import be.nikiroo.fanfix.Instance;
c1873e56
NR
14import be.nikiroo.fanfix.bundles.UiConfig;
15import be.nikiroo.fanfix.data.MetaData;
89cb07a6 16import be.nikiroo.fanfix.data.Story;
e42573a0 17import be.nikiroo.fanfix.library.BasicLibrary;
df6e2d88 18import be.nikiroo.utils.StringUtils;
89cb07a6
NR
19
20/**
dd56a893 21 * The class that handles the different {@link Story} readers you can use.
89cb07a6
NR
22 *
23 * @author niki
24 */
9b75402f 25public abstract class BasicReader {
3b2b638f
NR
26 /**
27 * Return an {@link URL} from this {@link String}, be it a file path or an
28 * actual {@link URL}.
29 *
30 * @param sourceString
31 * the source
32 *
33 * @return the corresponding {@link URL}
34 *
35 * @throws MalformedURLException
36 * if this is neither a file nor a conventional {@link URL}
37 */
38 public static URL getUrl(String sourceString) throws MalformedURLException {
39 if (sourceString == null || sourceString.isEmpty()) {
40 throw new MalformedURLException("Empty url");
41 }
42
43 URL source = null;
44 try {
45 source = new URL(sourceString);
46 } catch (MalformedURLException e) {
47 File sourceFile = new File(sourceString);
48 source = sourceFile.toURI().toURL();
49 }
50
51 return source;
52 }
c1873e56 53
df6e2d88
NR
54 /**
55 * Describe a {@link Story} from its {@link MetaData} and return a list of
56 * title/value that represent this {@link Story}.
57 *
58 * @param meta
59 * the {@link MetaData} to represent
60 *
61 * @return the information
62 */
a6c830bb
NR
63 public static Map<String, String> getMetaDesc(MetaData meta) {
64 Map<String, String> metaDesc = new TreeMap<String, String>();
df6e2d88
NR
65
66 // TODO: i18n
67
68 StringBuilder tags = new StringBuilder();
69 for (String tag : meta.getTags()) {
70 if (tags.length() > 0) {
71 tags.append(", ");
72 }
73 tags.append(tag);
74 }
75
d16065ec 76 // TODO: i18n
a6c830bb
NR
77 metaDesc.put("Author", meta.getAuthor());
78 metaDesc.put("Publication date", formatDate(meta.getDate()));
79 metaDesc.put("Published on", meta.getPublisher());
80 metaDesc.put("URL", meta.getUrl());
d16065ec
NR
81 String count = "";
82 if (meta.getWords() > 0) {
83 count = StringUtils.formatNumber(meta.getWords());
84 }
a98e49ee 85 if (meta.isImageDocument()) {
d16065ec 86 metaDesc.put("Number of images", count);
a98e49ee 87 } else {
d16065ec 88 metaDesc.put("Number of words", count);
a98e49ee 89 }
a6c830bb
NR
90 metaDesc.put("Source", meta.getSource());
91 metaDesc.put("Subject", meta.getSubject());
92 metaDesc.put("Language", meta.getLang());
93 metaDesc.put("Tags", tags.toString());
df6e2d88
NR
94
95 return metaDesc;
96 }
97
5dd985cf
NR
98 /**
99 * Open the {@link Story} with an external reader (the program will be
100 * passed the main file associated with this {@link Story}).
101 *
102 * @param lib
103 * the {@link BasicLibrary} to select the {@link Story} from
104 * @param luid
105 * the {@link Story} LUID
350bc060
NR
106 * @param sync
107 * execute the process synchronously (wait until it is terminated
108 * before returning)
5dd985cf
NR
109 *
110 * @throws IOException
111 * in case of I/O error
112 */
350bc060
NR
113 public void openExternal(BasicLibrary lib, String luid, boolean sync)
114 throws IOException {
b0e88ebd 115 MetaData meta = lib.getInfo(luid);
ff05b828 116 File target = lib.getFile(luid, null);
c1873e56 117
350bc060 118 openExternal(meta, target, sync);
c1873e56
NR
119 }
120
5dd985cf
NR
121 /**
122 * Open the {@link Story} with an external reader (the program will be
123 * passed the given target file).
124 *
125 * @param meta
126 * the {@link Story} to load
127 * @param target
128 * the target {@link File}
350bc060
NR
129 * @param sync
130 * execute the process synchronously (wait until it is terminated
131 * before returning)
5dd985cf
NR
132 *
133 * @throws IOException
134 * in case of I/O error
135 */
350bc060
NR
136 protected void openExternal(MetaData meta, File target, boolean sync)
137 throws IOException {
c1873e56
NR
138 String program = null;
139 if (meta.isImageDocument()) {
d66deb8d 140 program = Instance.getInstance().getUiConfig().getString(UiConfig.IMAGES_DOCUMENT_READER);
c1873e56 141 } else {
d66deb8d 142 program = Instance.getInstance().getUiConfig().getString(UiConfig.NON_IMAGES_DOCUMENT_READER);
c1873e56
NR
143 }
144
145 if (program != null && program.trim().isEmpty()) {
146 program = null;
147 }
148
350bc060 149 start(target, program, sync);
16a81ef7 150 }
c1873e56 151
16a81ef7
NR
152 /**
153 * Start a file and open it with the given program if given or the first
154 * default system starter we can find.
155 *
156 * @param target
157 * the target to open
158 * @param program
159 * the program to use or NULL for the default system starter
350bc060
NR
160 * @param sync
161 * execute the process synchronously (wait until it is terminated
162 * before returning)
16a81ef7
NR
163 *
164 * @throws IOException
165 * in case of I/O error
166 */
350bc060
NR
167 protected void start(File target, String program, boolean sync)
168 throws IOException {
169
170 Process proc = null;
16a81ef7
NR
171 if (program == null) {
172 boolean ok = false;
b4f9071c
NR
173 for (String starter : new String[] { "xdg-open", "open", "see",
174 "start", "run" }) {
16a81ef7 175 try {
d66deb8d
NR
176 Instance.getInstance().getTraceHandler().trace("starting external program");
177 proc = Runtime.getRuntime().exec(new String[] { starter, target.getAbsolutePath() });
16a81ef7
NR
178 ok = true;
179 break;
180 } catch (IOException e) {
181 }
182 }
183 if (!ok) {
184 throw new IOException("Cannot find a program to start the file");
c1873e56
NR
185 }
186 } else {
d66deb8d 187 Instance.getInstance().getTraceHandler().trace("starting external program");
350bc060 188 proc = Runtime.getRuntime().exec(
c1873e56
NR
189 new String[] { program, target.getAbsolutePath() });
190 }
350bc060
NR
191
192 if (proc != null && sync) {
9ce8d884
N
193 try {
194 proc.waitFor();
195 } catch (InterruptedException e) {
350bc060
NR
196 }
197 }
c1873e56 198 }
df6e2d88 199
df6e2d88
NR
200 static private String formatDate(String date) {
201 long ms = 0;
202
d16065ec 203 if (date != null && !date.isEmpty()) {
df6e2d88 204 try {
d16065ec 205 ms = StringUtils.toTime(date);
df6e2d88
NR
206 } catch (ParseException e) {
207 }
d16065ec
NR
208
209 if (ms <= 0) {
210 SimpleDateFormat sdf = new SimpleDateFormat(
211 "yyyy-MM-dd'T'HH:mm:ssSSS");
212 try {
213 ms = sdf.parse(date).getTime();
214 } catch (ParseException e) {
215 }
216 }
217
218 if (ms > 0) {
219 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
220 return sdf.format(new Date(ms));
221 }
df6e2d88
NR
222 }
223
d16065ec
NR
224 if (date == null) {
225 date = "";
df6e2d88
NR
226 }
227
228 // :(
229 return date;
230 }
89cb07a6 231}