1 package be
.nikiroo
.fanfix
.output
;
4 import java
.io
.IOException
;
6 import be
.nikiroo
.fanfix
.Instance
;
7 import be
.nikiroo
.fanfix
.bundles
.StringId
;
8 import be
.nikiroo
.fanfix
.data
.Chapter
;
9 import be
.nikiroo
.fanfix
.data
.Paragraph
;
10 import be
.nikiroo
.fanfix
.data
.Story
;
11 import be
.nikiroo
.fanfix
.data
.Paragraph
.ParagraphType
;
14 * This class is the base class used by the other output classes. It can be used
15 * outside of this package, and have static method that you can use to get
16 * access to the correct support class.
20 public abstract class BasicOutput
{
22 * The supported output types for which we can get a {@link BasicOutput}
27 public enum OutputType
{
28 /** EPUB files created with this program */
30 /** Pure text file with some rules */
32 /** TEXT but with associated .info file */
34 /** DEBUG output to console */
36 /** ZIP with (PNG) images */
38 /** LaTeX file with "book" template */
40 /** HTML files in a dedicated directory */
45 public String
toString() {
46 return super.toString().toLowerCase();
50 * A description of this output type.
52 * @return the description
54 public String
getDesc() {
55 String desc
= Instance
.getTrans().getStringX(StringId
.OUTPUT_DESC
,
59 desc
= Instance
.getTrans()
60 .getString(StringId
.OUTPUT_DESC
, this);
67 * The default extension to add to the output files.
69 * @return the extension
71 public String
getDefaultExtension() {
72 BasicOutput output
= BasicOutput
.getOutput(this, false);
74 return output
.getDefaultExtension();
81 * Call {@link OutputType#valueOf(String.toUpperCase())}.
84 * the possible type name
86 * @return NULL or the type
88 public static OutputType
valueOfUC(String typeName
) {
89 return OutputType
.valueOf(typeName
== null ?
null : typeName
94 * Call {@link OutputType#valueOf(String.toUpperCase())} but return NULL
95 * for NULL instead of raising exception.
98 * the possible type name
100 * @return NULL or the type
102 public static OutputType
valueOfNullOkUC(String typeName
) {
103 if (typeName
== null) {
107 return OutputType
.valueOfUC(typeName
);
111 * Call {@link OutputType#valueOf(String.toUpperCase())} but return NULL
112 * in case of error instead of raising an exception.
115 * the possible type name
117 * @return NULL or the type
119 public static OutputType
valueOfAllOkUC(String typeName
) {
121 return OutputType
.valueOfUC(typeName
);
122 } catch (Exception e
) {
128 /** The creator name (this program, by me!) */
129 static final String EPUB_CREATOR
= "Fanfix (by Niki)";
131 /** The current best name for an image */
132 private String imageName
;
133 private File targetDir
;
134 private String targetName
;
135 private OutputType type
;
136 private boolean writeCover
;
137 private boolean writeInfo
;
140 * Process the {@link Story} into the given target.
143 * the {@link Story} to export
145 * the target where to save to (will not necessary be taken as is
146 * by the processor, for instance an extension can be added)
148 * @return the actual main target saved, which can be slightly different
151 * @throws IOException
152 * in case of I/O error
154 public File
process(Story story
, String target
) throws IOException
{
155 target
= new File(target
).getAbsolutePath();
156 File targetDir
= new File(target
).getParentFile();
157 String targetName
= new File(target
).getName();
159 String ext
= getDefaultExtension();
160 if (ext
!= null && !ext
.isEmpty()) {
161 if (targetName
.toLowerCase().endsWith(ext
)) {
162 targetName
= targetName
.substring(0,
163 targetName
.length() - ext
.length());
167 return process(story
, targetDir
, targetName
);
171 * Process the {@link Story} into the given target.
173 * This method is expected to be overridden in most cases.
176 * the {@link Story} to export
178 * the target dir where to save to
180 * the target filename (will not necessary be taken as is by the
181 * processor, for instance an extension can be added)
183 * @return the actual main target saved, which can be slightly different
186 * @throws IOException
187 * in case of I/O error
189 protected File
process(Story story
, File targetDir
, String targetName
)
191 this.targetDir
= targetDir
;
192 this.targetName
= targetName
;
204 public OutputType
getType() {
214 * TRUE to enable the creation of a .info file and a cover if
219 protected BasicOutput
setType(OutputType type
, boolean writeCover
,
222 this.writeCover
= writeCover
;
223 this.writeInfo
= writeInfo
;
229 * The default extension to add to the output files.
231 * @return the extension
233 public String
getDefaultExtension() {
237 protected void writeStoryHeader(Story story
) throws IOException
{
240 protected void writeChapterHeader(Chapter chap
) throws IOException
{
243 protected void writeParagraphHeader(Paragraph para
) throws IOException
{
246 protected void writeStoryFooter(Story story
) throws IOException
{
249 protected void writeChapterFooter(Chapter chap
) throws IOException
{
252 protected void writeParagraphFooter(Paragraph para
) throws IOException
{
255 protected void writeStory(Story story
) throws IOException
{
256 String chapterNameNum
= String
.format("%03d", 0);
257 String paragraphNumber
= String
.format("%04d", 0);
258 imageName
= paragraphNumber
+ "_" + chapterNameNum
+ ".png";
260 if (story
.getMeta() != null) {
261 story
.getMeta().setType("" + getType());
265 InfoCover
.writeCover(targetDir
, targetName
, story
.getMeta());
268 InfoCover
.writeInfo(targetDir
, targetName
, story
.getMeta());
271 writeStoryHeader(story
);
272 for (Chapter chap
: story
) {
275 writeStoryFooter(story
);
278 protected void writeChapter(Chapter chap
) throws IOException
{
279 String chapterNameNum
;
280 if (chap
.getName() == null || chap
.getName().isEmpty()) {
281 chapterNameNum
= String
.format("%03d", chap
.getNumber());
283 chapterNameNum
= String
.format("%03d", chap
.getNumber()) + "_"
284 + chap
.getName().replace(" ", "_");
288 String paragraphNumber
= String
.format("%04d", num
++);
289 imageName
= chapterNameNum
+ "_" + paragraphNumber
+ ".png";
291 writeChapterHeader(chap
);
292 for (Paragraph para
: chap
) {
293 paragraphNumber
= String
.format("%04d", num
++);
294 imageName
= chapterNameNum
+ "_" + paragraphNumber
+ ".png";
295 writeParagraph(para
);
297 writeChapterFooter(chap
);
300 protected void writeParagraph(Paragraph para
) throws IOException
{
301 writeParagraphHeader(para
);
302 writeTextLine(para
.getType(), para
.getContent());
303 writeParagraphFooter(para
);
306 protected void writeTextLine(ParagraphType type
, String line
)
311 * Return the current best guess for an image name, based upon the current
312 * {@link Chapter} and {@link Paragraph}.
315 * add the original target name as a prefix
317 * @return the guessed name
319 protected String
getCurrentImageBestName(boolean prefix
) {
321 return targetName
+ "_" + imageName
;
328 * Return the given word or sentence as <b>bold</b>.
333 * @return the bold output
335 protected String
enbold(String word
) {
340 * Return the given word or sentence as <i>italic</i>.
345 * @return the italic output
347 protected String
italize(String word
) {
352 * Decorate the given text with <b>bold</b> and <i>italic</i> words,
353 * according to {@link BasicOutput#enbold(String)} and
354 * {@link BasicOutput#italize(String)}.
359 * @return the decorated output
361 protected String
decorateText(String text
) {
362 StringBuilder builder
= new StringBuilder();
367 for (char car
: text
.toCharArray()) {
370 if (bold
>= 0 && prev
!= ' ') {
371 String data
= builder
.substring(bold
);
372 builder
.setLength(bold
);
373 builder
.append(enbold(data
));
376 && (prev
== ' ' || prev
== '\0' || prev
== '\n')) {
377 bold
= builder
.length();
384 if (italic
>= 0 && prev
!= ' ') {
385 String data
= builder
.substring(italic
);
386 builder
.setLength(italic
);
387 builder
.append(enbold(data
));
389 } else if (italic
< 0
390 && (prev
== ' ' || prev
== '\0' || prev
== '\n')) {
391 italic
= builder
.length();
406 builder
.insert(bold
, '*');
410 builder
.insert(italic
, '_');
413 return builder
.toString();
417 * Return a {@link BasicOutput} object compatible with the given
418 * {@link OutputType}.
423 * force the <tt>.info</tt> file and the cover to be saved next
424 * to the main target file
426 * @return the {@link BasicOutput}
428 public static BasicOutput
getOutput(OutputType type
, boolean infoCover
) {
432 return new Epub().setType(type
, infoCover
, infoCover
);
434 return new Text().setType(type
, true, infoCover
);
436 return new InfoText().setType(type
, true, true);
438 return new Sysout().setType(type
, false, false);
440 return new Cbz().setType(type
, infoCover
, infoCover
);
442 return new LaTeX().setType(type
, infoCover
, infoCover
);
444 return new Html().setType(type
, false, false);