package info.toyonos.subtitles4j.factory; import info.toyonos.subtitles4j.helper.Subtitles4jUtils; import info.toyonos.subtitles4j.model.SubtitlesContainer; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; public class Subtitles4jFactory { protected static class Subtitles4jFactoryHolder { public static final Subtitles4jFactory instance = new Subtitles4jFactory(); } public static Subtitles4jFactory getInstance() { return Subtitles4jFactoryHolder.instance; } private Map<SubtitlesType, SubtitlesFactory> factories; /** * Private constructor for singleton */ private Subtitles4jFactory() { factories = new HashMap<>(); for (SubtitlesType type : SubtitlesType.values()) { try { factories.put(type, type.getClazz().newInstance()); } catch (Exception e) { throw new RuntimeException("The factory for the type " + type + " is missing !", e); } } } /** * <p>Construct a <code>SubtitlesContainer</code> from an input <code>File</code><p> * <p>The input <code>SubtitlesType</code> is determined through the filename extension<p> * @param input The input <code>File</code> to be parsed * @return the resulting <code>SubtitlesContainer</code> * @throws Subtitles4jException if the input is malformed, the extension not supported * @throws IOException if any IO error occurs */ public SubtitlesContainer fromFile(File input) throws Subtitles4jException, IOException { SubtitlesType inputType = Subtitles4jUtils.getType(input.getName()); if (inputType != null) { return factories.get(inputType).fromFile(input); } else { throw new UnsupportedSubtitlesExtension(FilenameUtils.getExtension(input.getName())); } } /** * <p>Construct a <code>SubtitlesContainer</code> from an <code>InputStream</code><p> * @param input The <code>InputStream</code> to be parsed * @param inputType the <code>SubtitlesType</code> of the input * @return the resulting <code>SubtitlesContainer</code> * @throws MalformedSubtitlesException if the extension not supported * @throws IOException if any IO error occurs */ public SubtitlesContainer fromStream(InputStream input, SubtitlesType inputType) throws MalformedSubtitlesException, IOException { return factories.get(inputType).fromStream(input); } /** * Convert a <code>SubtitlesContainer</code> to a <code>File</code>, for a target <code>SubtitlesType</code> * @param container the <code>SubtitlesContainer</code> to be converted * @param output the output <code>File</code> * @param type the target <code>SubtitlesType</code> * @return the generated output <code>File</code> * @throws SubtitlesGenerationException if an error occurs during the generation * @throws IOException if any IO error occurs */ public File toSubtitlesType(SubtitlesContainer container, File output, SubtitlesType type) throws SubtitlesGenerationException, IOException { return factories.get(type).toFile(container, output); } /** * Convert a <code>SubtitlesContainer</code> to a <code>OutputStream</code>, for a target <code>SubtitlesType</code> * @param container the <code>SubtitlesContainer</code> to be converted * @param output the <code>OutputStream</code> * @param type the target <code>SubtitlesType</code> * @return the generated <code>OutputStream</code> * @throws SubtitlesGenerationException if an error occurs during the generation */ public OutputStream toSubtitlesType(SubtitlesContainer container, OutputStream output, SubtitlesType type) throws SubtitlesGenerationException { return factories.get(type).toStream(container, output); } /** * Convert an input <code>File</code> to a target <code>SubtitlesType</code> * @param input the input <code>File</code> * @param output the output <code>File</code> * @param outputType the new wished <code>SubtitlesType</code> * @return the modified output <code>File</code> * @throws Subtitles4jException if an error occurs during the conversion * @throws IOException if any IO error occurs */ public File toSubtitlesType(File input, File output, SubtitlesType outputType) throws Subtitles4jException, IOException { String ext = FilenameUtils.getExtension(input.getName()); if (outputType.hasExtension(ext)) { // Same input/output extension return input; } else { return factories.get(outputType).toFile(fromFile(input), output); } } /** * Convert an <code>InputStream</code> to a target <code>SubtitlesType</code> * @param input the <code>InputStream</code> * @param inputType the <code>SubtitlesType</code> of the input * @param output the <code>OutputStream</code> * @param outputType the new wished <code>SubtitlesType</code> * @return the converted code>OutputStream</code> * @throws Subtitles4jException if an error occurs during the conversion * @throws IOException if any IO error occurs */ public OutputStream toSubtitlesType(InputStream input, SubtitlesType inputType, OutputStream output, SubtitlesType outputType) throws Subtitles4jException, IOException { if (outputType == inputType) { // Same input/output type IOUtils.copy(input, output); return output; } else { return factories.get(outputType).toStream(fromStream(input, inputType), output); } } /* Shortcut methods for all types */ /** * Equivalent to {@link #toSubtitlesType(SubtitlesContainer, File, SubtitlesType)} for <code>SubtitlesType.SRT</code> */ public File toSRT(SubtitlesContainer container, File output) throws SubtitlesGenerationException, IOException { return factories.get(SubtitlesType.SRT).toFile(container, output); } /** * Equivalent to {@link #toSubtitlesType(SubtitlesContainer, OutputStream, SubtitlesType) } for <code>SubtitlesType.SRT</code> */ public OutputStream toSRT(SubtitlesContainer container, OutputStream output) throws SubtitlesGenerationException, IOException { return factories.get(SubtitlesType.SRT).toStream(container, output); } /** * Equivalent to {@link #toSubtitlesType(SubtitlesContainer, File, SubtitlesType)} for <code>SubtitlesType.ASS</code> */ public File toASS(SubtitlesContainer container, File output) throws SubtitlesGenerationException, IOException { return factories.get(SubtitlesType.ASS).toFile(container, output); } /** * Equivalent to {@link #toSubtitlesType(SubtitlesContainer, OutputStream, SubtitlesType) } for <code>SubtitlesType.ASS</code> */ public OutputStream toASS(SubtitlesContainer container, OutputStream output) throws SubtitlesGenerationException, IOException { return factories.get(SubtitlesType.ASS).toStream(container, output); } /** * Equivalent to {@link #toSubtitlesType(File, File, SubtitlesType)} for <code>SubtitlesType.SRT</code> */ public File toSRT(File input, File output) throws Subtitles4jException, IOException { return toSubtitlesType(input, output, SubtitlesType.SRT); } /** * Equivalent to {@link #toSubtitlesType(InputStream, SubtitlesType, OutputStream, SubtitlesType)} for <code>SubtitlesType.SRT</code> */ public OutputStream toSRT(InputStream input, SubtitlesType inputType, OutputStream output) throws Subtitles4jException, IOException { return toSubtitlesType(input, inputType, output, SubtitlesType.SRT); } /** * Equivalent to {@link #toSubtitlesType(File, File, SubtitlesType)} for <code>SubtitlesType.ASS</code> */ public File toASS(File input, File output) throws Subtitles4jException, IOException { return toSubtitlesType(input, output, SubtitlesType.ASS); } /** * Equivalent to {@link #toSubtitlesType(InputStream, SubtitlesType, OutputStream, SubtitlesType)} for <code>SubtitlesType.ASS</code> */ public OutputStream toASS(InputStream input, SubtitlesType inputType, OutputStream output) throws Subtitles4jException, IOException { return toSubtitlesType(input, inputType, output, SubtitlesType.ASS); } }