1 package be
.nikiroo
.fanfix
.supported
;
3 import java
.awt
.image
.BufferedImage
;
5 import java
.io
.IOException
;
6 import java
.io
.InputStream
;
7 import java
.net
.URISyntaxException
;
9 import java
.util
.ArrayList
;
10 import java
.util
.List
;
11 import java
.util
.Map
.Entry
;
12 import java
.util
.Scanner
;
14 import be
.nikiroo
.fanfix
.Instance
;
15 import be
.nikiroo
.fanfix
.bundles
.Config
;
16 import be
.nikiroo
.fanfix
.data
.MetaData
;
19 * Support class for local stories encoded in textual format, with a few rules:
21 * <li>The title must be on the first line</li>
22 * <li>The author (preceded by nothing, "by " or "©") must be on the second
23 * line, possibly with the publication date in parenthesis (i.e., "
24 * <tt>By Unknown (3rd October 1998)</tt>")</li>
25 * <li>Chapters must be declared with "<tt>Chapter x</tt>" or "
26 * <tt>Chapter x: NAME OF THE CHAPTER</tt>", where "<tt>x</tt>" is the chapter
28 * <li>A description of the story must be given as chapter number 0</li>
29 * <li>A cover may be present, with the same filename but a PNG, JPEG or JPG
35 class Text
extends BasicSupport
{
37 protected boolean isHtml() {
42 public String
getSourceName() {
47 protected MetaData
getMeta(URL source
, InputStream in
) throws IOException
{
48 MetaData meta
= new MetaData();
50 meta
.setTitle(getTitle(reset(in
)));
51 meta
.setAuthor(getAuthor(reset(in
)));
52 meta
.setDate(getDate(reset(in
)));
53 meta
.setTags(new ArrayList
<String
>());
54 meta
.setSource(getSourceName());
55 meta
.setUrl(source
.toString());
56 meta
.setPublisher("");
57 meta
.setUuid(source
.toString());
59 meta
.setLang(getLang(source
, reset(in
))); // default is EN
60 meta
.setSubject(getSubject(source
));
61 meta
.setType(getType().toString());
62 meta
.setImageDocument(false);
63 meta
.setCover(getCover(source
));
68 private String
getSubject(URL source
) throws IOException
{
70 File file
= new File(source
.toURI());
71 return file
.getParentFile().getName();
72 } catch (URISyntaxException e
) {
73 throw new IOException("Cannot parse the URL to File: "
74 + source
.toString(), e
);
79 private String
getLang(URL source
, InputStream in
) throws IOException
{
80 @SuppressWarnings("resource")
81 Scanner scan
= new Scanner(in
, "UTF-8");
82 scan
.useDelimiter("\\n");
84 scan
.next(); // Author (Date)
85 String chapter0
= scan
.next(); // empty or Chapter 0
86 while (chapter0
.isEmpty()) {
87 chapter0
= scan
.next();
90 String lang
= detectChapter(chapter0
);
94 lang
= lang
.toUpperCase();
100 private String
getTitle(InputStream in
) throws IOException
{
101 @SuppressWarnings("resource")
102 Scanner scan
= new Scanner(in
, "UTF-8");
103 scan
.useDelimiter("\\n");
107 private String
getAuthor(InputStream in
) throws IOException
{
108 @SuppressWarnings("resource")
109 Scanner scan
= new Scanner(in
, "UTF-8");
110 scan
.useDelimiter("\\n");
112 String authorDate
= scan
.next();
114 String author
= authorDate
;
115 int pos
= authorDate
.indexOf('(');
117 author
= authorDate
.substring(0, pos
);
120 return fixAuthor(author
);
123 private String
getDate(InputStream in
) throws IOException
{
124 @SuppressWarnings("resource")
125 Scanner scan
= new Scanner(in
, "UTF-8");
126 scan
.useDelimiter("\\n");
128 String authorDate
= scan
.next();
131 int pos
= authorDate
.indexOf('(');
133 date
= authorDate
.substring(pos
+ 1).trim();
134 pos
= date
.lastIndexOf(')');
136 date
= date
.substring(0, pos
).trim();
144 protected String
getDesc(URL source
, InputStream in
) throws IOException
{
145 return getChapterContent(source
, in
, 0);
148 private BufferedImage
getCover(URL source
) throws IOException
{
151 path
= new File(source
.toURI()).getPath();
152 } catch (URISyntaxException e
) {
157 for (String ext
: new String
[] { ".txt", ".text", ".story" }) {
158 if (path
.endsWith(ext
)) {
159 path
= path
.substring(0, path
.length() - ext
.length());
163 return getImage(this, source
, path
);
167 protected List
<Entry
<String
, URL
>> getChapters(URL source
, InputStream in
)
169 List
<Entry
<String
, URL
>> chaps
= new ArrayList
<Entry
<String
, URL
>>();
170 @SuppressWarnings("resource")
171 Scanner scan
= new Scanner(in
, "UTF-8");
172 scan
.useDelimiter("\\n");
173 boolean descSkipped
= false;
174 boolean prevLineEmpty
= false;
175 while (scan
.hasNext()) {
176 String line
= scan
.next();
177 if (prevLineEmpty
&& detectChapter(line
) != null) {
179 String chapName
= Integer
.toString(chaps
.size());
180 int pos
= line
.indexOf(':');
181 if (pos
>= 0 && pos
+ 1 < line
.length()) {
182 chapName
= line
.substring(pos
+ 1).trim();
184 final URL value
= source
;
185 final String key
= chapName
;
186 chaps
.add(new Entry
<String
, URL
>() {
187 public URL
setValue(URL value
) {
191 public URL
getValue() {
195 public String
getKey() {
204 prevLineEmpty
= line
.trim().isEmpty();
211 protected String
getChapterContent(URL source
, InputStream in
, int number
)
213 StringBuilder builder
= new StringBuilder();
214 @SuppressWarnings("resource")
215 Scanner scan
= new Scanner(in
, "UTF-8");
216 scan
.useDelimiter("\\n");
217 boolean inChap
= false;
218 while (scan
.hasNext()) {
219 String line
= scan
.next();
220 if (detectChapter(line
, number
) != null) {
222 } else if (inChap
&& detectChapter(line
) != null) {
225 builder
.append(line
);
226 builder
.append("\n");
230 return builder
.toString();
234 protected boolean supports(URL url
) {
235 if ("file".equals(url
.getProtocol())) {
238 file
= new File(url
.toURI());
239 file
= new File(file
.getPath() + ".info");
240 } catch (URISyntaxException e
) {
245 return file
== null || !file
.exists();
252 * Check if the given line looks like a starting chapter in a supported
253 * language, and return the language if it does (or NULL if not).
258 * @return the language or NULL
260 private String
detectChapter(String line
) {
261 return detectChapter(line
, null);
265 * Check if the given line looks like the given starting chapter in a
266 * supported language, and return the language if it does (or NULL if not).
271 * @return the language or NULL
273 private String
detectChapter(String line
, Integer number
) {
274 line
= line
.toUpperCase();
275 for (String lang
: Instance
.getConfig().getString(Config
.CHAPTER
)
277 String chapter
= Instance
.getConfig().getStringX(Config
.CHAPTER
,
279 if (chapter
!= null && !chapter
.isEmpty()) {
280 chapter
= chapter
.toUpperCase() + " ";
281 if (line
.startsWith(chapter
)) {
282 if (number
!= null) {
283 // We want "[CHAPTER] [number]: [name]", with ": [name]"
285 String test
= line
.substring(chapter
.length()).trim();
286 if (test
.startsWith(Integer
.toString(number
))) {
287 test
= test
.substring(
288 Integer
.toString(number
).length()).trim();
289 if (test
.isEmpty() || test
.startsWith(":")) {