nihas101/java-kotlin-images-to-pdf-converter

View on GitHub
src/main/kotlin/de/nihas101/image_to_pdf_converter/directory_iterators/image_iterators/ImageDirectoriesIterator.kt

Summary

Maintainability
B
4 hrs
Test Coverage
/*
 JaKoImage2PDF is a program for converting images to PDFs with the use of iText 7
 Copyright (C) 2018  Nikita Hasert

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package de.nihas101.image_to_pdf_converter.directory_iterators.image_iterators

import de.nihas101.image_to_pdf_converter.directory_iterators.DirectoryIterator
import de.nihas101.image_to_pdf_converter.directory_iterators.exceptions.ExtensionNotSupportedException
import de.nihas101.image_to_pdf_converter.directory_iterators.image_iterators.ImageFilesIterator.ImageFilesIteratorFactory.isImage
import de.nihas101.image_to_pdf_converter.directory_iterators.zip_iterators.ImageUnZipper.ZipFileIteratorFactory.canUnzip
import de.nihas101.image_to_pdf_converter.pdf.pdf_options.IteratorOptions
import de.nihas101.image_to_pdf_converter.util.JaKoLogger
import de.nihas101.image_to_pdf_converter.util.ProgressUpdater
import de.nihas101.image_to_pdf_converter.util.RecursiveFileSearcher.RecursiveFileSearcherFactory.createRecursiveFileSearcher
import java.io.File

open class ImageDirectoriesIterator protected constructor(iteratorOptions: IteratorOptions) : DirectoryIterator(iteratorOptions) {
    override fun getParentDirectory(): File = directory!!

    override fun canBeAdded(file: File) = isImageDirectory(file) || canUnzip(file)

    override fun add(index: Int, file: File): Boolean {
        val arguments = Array<Any>(2) {}
        arguments[0] = file.name
        arguments[1] = index

        return when {
            isImageDirectory(file) -> {
                files.add(index, file)
                logger.info("Added {} at index {}", arguments)
                true
            }
            canUnzip(file) -> add(unzip(file))
            else -> {
                logger.info("Ignored addition of {} at index {} as it cannot be added", arguments)
                false
            }
        }
    }

    override fun addDirectory(file: File, progressUpdater: ProgressUpdater): Boolean {
        super.setupDirectory(file, progressUpdater)

        val recursiveFileSearcher = createRecursiveFileSearcher(file)
        val files = recursiveFileSearcher.searchRecursively(iteratorOptions.maximalSearchDepth, progressUpdater)
        { fileToAdd -> canBeAdded(fileToAdd) }

        return if (files.isEmpty()) {
            setupDirectory(file)
            true
        } else {
            addAll(files.filter(this@ImageDirectoriesIterator::canBeAdded), progressUpdater)
        }
    }

    override fun addAll(filesToAdd: List<File>, progressUpdater: ProgressUpdater): Boolean {
        val processedFiles = mutableListOf<File>()

        if (filesToAdd.isEmpty()) return true
        if (files.isEmpty()) setupDirectory(filesToAdd[0].parentFile, progressUpdater)
        val outOf = filesToAdd.size

        filesToAdd.forEachIndexed { index, file ->
            processedFiles.addAll(processFile(file))
            progressUpdater.updateProgress((index + 1).toDouble() / outOf.toDouble(), file)
        }

        return files.addAll(processedFiles)
    }

    private fun processFile(file: File): MutableList<File> {
        val processedFiles = mutableListOf<File>()

        if (canUnzip(file)) processedFiles.addAll(tryToUnzip(file))
        else if (isImageDirectory(file)) processedFiles.add(file)

        return processedFiles
    }

    private fun tryToUnzip(file: File): List<File> {
        val unzippedFiles = mutableListOf<File>()

        try {
            unzippedFiles.add(unzip(file))
        } catch (exception: ExtensionNotSupportedException) {
            logger.info("Skipping {} as it cannot be unzipped.", file)
        }

        return unzippedFiles
    }

    private fun isImageDirectory(directory: File): Boolean {
        if (!directory.isDirectory) return false

        directory.listFiles().forEach { file -> if (isImage(file)) return true }
        return false
    }

    companion object ImageDirectoriesIteratorFactory {
        private val logger = JaKoLogger.createLogger(this::class.java)!!

        fun createImageDirectoriesIterator(iteratorOptions: IteratorOptions): ImageDirectoriesIterator = ImageDirectoriesIterator(iteratorOptions)
    }
}