Merge branch WIP back into master:
[fanfix.git] / src / be / nikiroo / fanfix / supported / Cbz.java
1 package be.nikiroo.fanfix.supported;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.net.URL;
8 import java.util.ArrayList;
9 import java.util.Collections;
10 import java.util.HashMap;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.zip.ZipEntry;
14 import java.util.zip.ZipInputStream;
15
16 import be.nikiroo.fanfix.Instance;
17 import be.nikiroo.fanfix.data.Chapter;
18 import be.nikiroo.fanfix.data.MetaData;
19 import be.nikiroo.fanfix.data.Paragraph;
20 import be.nikiroo.fanfix.data.Story;
21 import be.nikiroo.utils.IOUtils;
22 import be.nikiroo.utils.Image;
23 import be.nikiroo.utils.MarkableFileInputStream;
24 import be.nikiroo.utils.Progress;
25
26 /**
27 * Support class for CBZ files (works better with CBZ created with this program,
28 * as they have some metadata available).
29 *
30 * @author niki
31 */
32 class Cbz extends Epub {
33 @Override
34 protected boolean supports(URL url) {
35 return url.toString().toLowerCase().endsWith(".cbz");
36 }
37
38 @Override
39 public String getSourceName() {
40 return "cbz";
41 }
42
43 @Override
44 protected String getDataPrefix() {
45 return "";
46 }
47
48 @Override
49 protected boolean requireInfo() {
50 return false;
51 }
52
53 @Override
54 protected boolean isImagesDocumentByDefault() {
55 return true;
56 }
57
58 @Override
59 protected boolean getCover() {
60 return false;
61 }
62
63 @Override
64 public Story doProcess(Progress pg) throws IOException {
65 if (pg == null) {
66 pg = new Progress();
67 } else {
68 pg.setMinMax(0, 100);
69 }
70
71 Progress pgMeta = new Progress();
72 pg.addProgress(pgMeta, 10);
73 Story story = processMeta(true, pgMeta);
74 MetaData meta = story.getMeta();
75
76 pgMeta.done(); // 10%
77
78 File tmpDir = Instance.getTempFiles().createTempDir("info-text");
79 String basename = null;
80
81 Map<String, Image> images = new HashMap<String, Image>();
82 InputStream cbzIn = null;
83 ZipInputStream zipIn = null;
84 try {
85 cbzIn = new MarkableFileInputStream(new FileInputStream(
86 getSourceFileOriginal()));
87 zipIn = new ZipInputStream(cbzIn);
88 for (ZipEntry entry = zipIn.getNextEntry(); entry != null; entry = zipIn
89 .getNextEntry()) {
90 if (!entry.isDirectory()
91 && entry.getName().startsWith(getDataPrefix())) {
92 String entryLName = entry.getName().toLowerCase();
93 boolean imageEntry = false;
94 for (String ext : BasicSupportImages.getImageExt(false)) {
95 if (entryLName.endsWith(ext)) {
96 imageEntry = true;
97 }
98 }
99
100 if (imageEntry) {
101 String uuid = meta.getUuid() + "_" + entry.getName();
102 try {
103 images.put(uuid, new Image(zipIn));
104 } catch (Exception e) {
105 Instance.getTraceHandler().error(e);
106 }
107
108 if (pg.getProgress() < 85) {
109 pg.add(1);
110 }
111 } else if (entryLName.endsWith(".info")) {
112 basename = entryLName.substring(0, entryLName.length()
113 - ".info".length());
114 IOUtils.write(zipIn, new File(tmpDir, entryLName));
115 } else if (entryLName.endsWith(".txt")) {
116 IOUtils.write(zipIn, new File(tmpDir, entryLName));
117 }
118 }
119 }
120
121 pg.setProgress(85);
122
123 // ZIP order is not correct for us
124 List<String> imagesList = new ArrayList<String>(images.keySet());
125 Collections.sort(imagesList);
126
127 pg.setProgress(90);
128
129 // include original story
130 Story origStory = getStoryFromTxt(tmpDir, basename);
131 if (origStory != null) {
132 story.setChapters(origStory.getChapters());
133 story.setMeta(origStory.getMeta());
134 } else {
135 story.setChapters(new ArrayList<Chapter>());
136 }
137
138 if (!imagesList.isEmpty()) {
139 Chapter chap = new Chapter(story.getChapters().size() + 1, null);
140 story.getChapters().add(chap);
141
142 for (String uuid : imagesList) {
143 try {
144 chap.getParagraphs().add(
145 new Paragraph(images.get(uuid)));
146 } catch (Exception e) {
147 Instance.getTraceHandler().error(e);
148 }
149 }
150 }
151
152 if (meta.getCover() == null && !images.isEmpty()) {
153 meta.setCover(images.get(imagesList.get(0)));
154 meta.setFakeCover(true);
155 }
156
157 } finally {
158 IOUtils.deltree(tmpDir);
159 if (zipIn != null) {
160 zipIn.close();
161 }
162 if (cbzIn != null) {
163 cbzIn.close();
164 }
165 }
166
167 pg.setProgress(100);
168 return story;
169 }
170
171 private Story getStoryFromTxt(File tmpDir, String basename) {
172 Story origStory = null;
173
174 File txt = new File(tmpDir, basename + ".txt");
175 if (!txt.exists()) {
176 basename = null;
177 }
178 if (basename != null) {
179 try {
180 BasicSupport support = BasicSupport.getSupport(txt.toURI()
181 .toURL());
182 origStory = support.process(null);
183 } catch (Exception e) {
184 basename = null;
185 }
186 }
187
188 return origStory;
189
190 }
191 }