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
, 0);
93 lang
= detectChapter(chapter0
, 1);
99 lang
= lang
.toUpperCase();
105 private String
getTitle(InputStream in
) throws IOException
{
106 @SuppressWarnings("resource")
107 Scanner scan
= new Scanner(in
, "UTF-8");
108 scan
.useDelimiter("\\n");
112 private String
getAuthor(InputStream in
) throws IOException
{
113 @SuppressWarnings("resource")
114 Scanner scan
= new Scanner(in
, "UTF-8");
115 scan
.useDelimiter("\\n");
117 String authorDate
= scan
.next();
119 String author
= authorDate
;
120 int pos
= authorDate
.indexOf('(');
122 author
= authorDate
.substring(0, pos
);
125 return fixAuthor(author
);
128 private String
getDate(InputStream in
) throws IOException
{
129 @SuppressWarnings("resource")
130 Scanner scan
= new Scanner(in
, "UTF-8");
131 scan
.useDelimiter("\\n");
133 String authorDate
= scan
.next();
136 int pos
= authorDate
.indexOf('(');
138 date
= authorDate
.substring(pos
+ 1).trim();
139 pos
= date
.lastIndexOf(')');
141 date
= date
.substring(0, pos
).trim();
149 protected String
getDesc(URL source
, InputStream in
) throws IOException
{
150 return getChapterContent(source
, in
, 0);
153 private BufferedImage
getCover(URL source
) throws IOException
{
156 path
= new File(source
.toURI()).getPath();
157 } catch (URISyntaxException e
) {
162 for (String ext
: new String
[] { ".txt", ".text", ".story" }) {
163 if (path
.endsWith(ext
)) {
164 path
= path
.substring(0, path
.length() - ext
.length());
168 return getImage(this, source
, path
);
172 protected List
<Entry
<String
, URL
>> getChapters(URL source
, InputStream in
)
174 List
<Entry
<String
, URL
>> chaps
= new ArrayList
<Entry
<String
, URL
>>();
175 @SuppressWarnings("resource")
176 Scanner scan
= new Scanner(in
, "UTF-8");
177 scan
.useDelimiter("\\n");
178 boolean prevLineEmpty
= false;
179 while (scan
.hasNext()) {
180 String line
= scan
.next();
181 if (prevLineEmpty
&& detectChapter(line
, chaps
.size() + 1) != null) {
182 String chapName
= Integer
.toString(chaps
.size() + 1);
183 int pos
= line
.indexOf(':');
184 if (pos
>= 0 && pos
+ 1 < line
.length()) {
185 chapName
= line
.substring(pos
+ 1).trim();
187 final URL value
= source
;
188 final String key
= chapName
;
189 chaps
.add(new Entry
<String
, URL
>() {
190 public URL
setValue(URL value
) {
194 public URL
getValue() {
198 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
, number
+ 1) != 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 the given starting chapter in a
253 * supported language, and return the language if it does (or NULL if not).
258 * @return the language or NULL
260 private String
detectChapter(String line
, int number
) {
261 line
= line
.toUpperCase();
262 for (String lang
: Instance
.getConfig().getString(Config
.CHAPTER
)
264 String chapter
= Instance
.getConfig().getStringX(Config
.CHAPTER
,
266 if (chapter
!= null && !chapter
.isEmpty()) {
267 chapter
= chapter
.toUpperCase() + " ";
268 if (line
.startsWith(chapter
)) {
269 // We want "[CHAPTER] [number]: [name]", with ": [name]"
271 String test
= line
.substring(chapter
.length()).trim();
272 if (test
.startsWith(Integer
.toString(number
))) {
274 .substring(Integer
.toString(number
).length())
276 if (test
.isEmpty() || test
.startsWith(":")) {