1 package be
.nikiroo
.fanfix
;
4 import java
.io
.IOException
;
6 import java
.util
.ArrayList
;
7 import java
.util
.HashMap
;
10 import java
.util
.Map
.Entry
;
12 import be
.nikiroo
.fanfix
.data
.MetaData
;
13 import be
.nikiroo
.fanfix
.data
.Story
;
14 import be
.nikiroo
.fanfix
.output
.BasicOutput
;
15 import be
.nikiroo
.fanfix
.output
.BasicOutput
.OutputType
;
16 import be
.nikiroo
.fanfix
.supported
.BasicSupport
;
17 import be
.nikiroo
.fanfix
.supported
.BasicSupport
.SupportType
;
18 import be
.nikiroo
.fanfix
.supported
.InfoReader
;
21 * Manage a library of Stories: import, export, list.
23 * Each {@link Story} object will be associated with a (local to the library)
24 * unique ID, the LUID, which will be used to identify the {@link Story}.
28 public class Library
{
30 private Map
<MetaData
, File
> stories
;
32 private OutputType text
;
33 private OutputType image
;
36 * Create a new {@link Library} with the given backend directory.
39 * the directory where to find the {@link Story} objects
41 * the {@link OutputType} to save the text-focused stories into
43 * the {@link OutputType} to save the images-focused stories into
45 public Library(File dir
, OutputType text
, OutputType image
) {
47 this.stories
= new HashMap
<MetaData
, File
>();
56 * List all the stories of the given source type in the {@link Library}, or
57 * all the stories if NULL is passed as a type.
60 * the type of story to retrieve, or NULL for all
64 public List
<MetaData
> getList(SupportType type
) {
65 String typeString
= type
== null ?
null : type
.getSourceName();
67 List
<MetaData
> list
= new ArrayList
<MetaData
>();
68 for (Entry
<MetaData
, File
> entry
: getStories().entrySet()) {
69 String storyType
= entry
.getValue().getParentFile().getName();
70 if (typeString
== null || typeString
.equalsIgnoreCase(storyType
)) {
71 list
.add(entry
.getKey());
79 * Retrieve a {@link File} corresponding to the given {@link Story}.
82 * the Library UID of the story
84 * @return the corresponding {@link Story}
86 public MetaData
getInfo(String luid
) {
88 for (Entry
<MetaData
, File
> entry
: getStories().entrySet()) {
89 if (luid
.equals(entry
.getKey().getLuid())) {
90 return entry
.getKey();
99 * Retrieve a {@link File} corresponding to the given {@link Story}.
102 * the Library UID of the story
104 * @return the corresponding {@link Story}
106 public File
getFile(String luid
) {
108 for (Entry
<MetaData
, File
> entry
: getStories().entrySet()) {
109 if (luid
.equals(entry
.getKey().getLuid())) {
110 return entry
.getValue();
119 * Retrieve a specific {@link Story}.
122 * the Library UID of the story
124 * @return the corresponding {@link Story}
126 public Story
getStory(String luid
) {
128 for (Entry
<MetaData
, File
> entry
: getStories().entrySet()) {
129 if (luid
.equals(entry
.getKey().getLuid())) {
131 SupportType type
= SupportType
.valueOfAllOkUC(entry
132 .getKey().getType());
133 URL url
= entry
.getValue().toURI().toURL();
135 return BasicSupport
.getSupport(type
).process(url
);
137 throw new IOException("Unknown type: "
138 + entry
.getKey().getType());
140 } catch (IOException e
) {
141 // We should not have not-supported files in the
143 Instance
.syserr(new IOException(
144 "Cannot load file from library: "
145 + entry
.getValue().getPath(), e
));
155 * Import the {@link Story} at the given {@link URL} into the
159 * the {@link URL} to import
161 * @return the imported {@link Story}
163 * @throws IOException
164 * in case of I/O error
166 public Story
imprt(URL url
) throws IOException
{
167 BasicSupport support
= BasicSupport
.getSupport(url
);
168 if (support
== null) {
169 throw new IOException("URL not supported: " + url
.toString());
172 return save(support
.process(url
), null);
176 * Export the {@link Story} to the given target in the given format.
179 * the {@link Story} ID
181 * the {@link OutputType} to transform it to
183 * the target to save to
185 * @return the saved resource (the main saved {@link File})
187 * @throws IOException
188 * in case of I/O error
190 public File
export(String luid
, OutputType type
, String target
)
192 BasicOutput out
= BasicOutput
.getOutput(type
, true);
194 throw new IOException("Output type not supported: " + type
);
197 return out
.process(getStory(luid
), target
);
201 * Save a {@link Story} to the {@link Library}.
204 * the {@link Story} to save
206 * @return the same {@link Story}, whose LUID may have changed
208 * @throws IOException
209 * in case of I/O error
211 public Story
save(Story story
) throws IOException
{
212 return save(story
, null);
216 * Save a {@link Story} to the {@link Library} -- the LUID <b>must</b> be
217 * correct, or NULL to get the next free one.
220 * the {@link Story} to save
222 * the <b>correct</b> LUID or NULL to get the next free one
224 * @return the same {@link Story}, whose LUID may have changed
226 * @throws IOException
227 * in case of I/O error
229 private Story
save(Story story
, String luid
) throws IOException
{
230 MetaData key
= story
.getMeta().clone();
232 if (luid
== null || luid
.isEmpty()) {
233 getStories(); // refresh lastId if needed
234 key
.setLuid(String
.format("%03d", (++lastId
)));
239 getDir(key
).mkdirs();
240 if (!getDir(key
).exists()) {
241 throw new IOException("Cannot create library dir");
245 if (key
!= null && key
.isImageDocument()) {
251 BasicOutput it
= BasicOutput
.getOutput(out
, true);
252 File file
= it
.process(story
, getFile(key
).getPath());
253 getStories().put(story
.getMeta(), file
);
259 * The directory (full path) where the {@link Story} related to this
260 * {@link MetaData} should be located on disk.
263 * the {@link Story} {@link MetaData}
265 * @return the target directory
267 private File
getDir(MetaData key
) {
268 String source
= key
.getSource().replaceAll("[^a-zA-Z0-9._+-]", "_");
269 return new File(baseDir
, source
);
273 * The target (full path) where the {@link Story} related to this
274 * {@link MetaData} should be located on disk.
277 * the {@link Story} {@link MetaData}
281 private File
getFile(MetaData key
) {
282 String title
= key
.getTitle().replaceAll("[^a-zA-Z0-9._+-]", "_");
283 return new File(getDir(key
), key
.getLuid() + "_" + title
);
287 * Return all the known stories in this {@link Library} object.
289 * @return the stories
291 private Map
<MetaData
, File
> getStories() {
292 if (stories
.isEmpty()) {
295 String ext
= ".info";
296 for (File dir
: baseDir
.listFiles()) {
297 if (dir
.isDirectory()) {
298 for (File file
: dir
.listFiles()) {
300 if (file
.getPath().toLowerCase().endsWith(ext
)) {
301 MetaData meta
= InfoReader
.readMeta(file
);
303 int id
= Integer
.parseInt(meta
.getLuid());
308 // Replace .info with whatever is needed:
309 String path
= file
.getPath();
310 path
= path
.substring(0, path
.length()
313 String newExt
= getOutputType(meta
)
314 .getDefaultExtension();
316 file
= new File(path
+ newExt
);
319 stories
.put(meta
, file
);
321 } catch (Exception e
) {
323 Instance
.syserr(new IOException(
324 "Cannot understand the LUID of "
325 + file
.getPath() + ": "
326 + meta
.getLuid(), e
));
329 } catch (IOException e
) {
330 // We should not have not-supported files in the
332 Instance
.syserr(new IOException(
333 "Cannot load file from library: "
334 + file
.getPath(), e
));
345 * Return the {@link OutputType} for this {@link Story}.
348 * the {@link Story} {@link MetaData}
352 private OutputType
getOutputType(MetaData meta
) {
353 if (meta
!= null && meta
.isImageDocument()) {