silentbalanceyh/vertx-zero

View on GitHub
vertx-gaia/vertx-ams/src/main/java/io/horizon/util/Io.java

Summary

Maintainability
A
2 hrs
Test Coverage
package io.horizon.util;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import io.horizon.annotations.ChatGPT;
import io.horizon.eon.VString;
import io.horizon.eon.VValue;
import io.horizon.eon.em.EmType;
import io.horizon.exception.internal.EmptyIoException;
import io.horizon.exception.internal.JsonFormatException;
import io.horizon.fn.HFn;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;

import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * The library for IO resource reading.
 */
final class Io {
    /**
     * Yaml
     **/
    private static final ObjectMapper YAML = new YAMLMapper();

    /**
     * 「DEAD-LOCK」LoggerFactory.getLogger
     * Do not use `Annal` logger because of deadlock.
     */
    private static final LogUtil LOG = LogUtil.from(Io.class);

    private Io() {
    }

    static JsonArray ioJArray(final String filename) {
        final JsonArray content;
        try {
            content = new JsonArray(ioString(filename, null));
        } catch (final Throwable ex) {
            throw new JsonFormatException(Io.class, filename);
        }
        return content;
    }

    static JsonObject ioJObject(final String filename) {
        final JsonObject content;
        try {
            content = new JsonObject(ioString(filename, null));
        } catch (final Throwable ex) {
            throw new JsonFormatException(Io.class, filename);
        }
        return content;
    }

    static String ioString(final InputStream in, final String joined) {
        final StringBuilder buffer = new StringBuilder();
        return HFn.failOr(() -> {
            try (final BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
                // Character stream
                String line;
                while (null != (line = reader.readLine())) {
                    buffer.append(line);
                    if (!TIs.isNil(joined)) {
                        buffer.append(joined);
                    }
                }
                return buffer.toString();
            }
        }, in);
    }

    static String ioString(final String filename, final String joined) {
        return HFn.failOr(() -> ioString(IoStream.read(filename), joined), filename);
    }

    /**
     * Read yaml to JsonObject
     *
     * @param filename input filename
     *
     * @return Deserialized type of T
     */
    @SuppressWarnings("unchecked")
    static <T> T ioYaml(final String filename) {
        if (TIs.isNil(filename)) {
            /*
             * If filename is null or empty
             * return to null reference for future usage
             */
            return null;
        }
        final EmType.Yaml type = getYamlType(filename);
        if (Objects.isNull(type)) {
            return null;
        }
        final String literal = getYamlNode(filename).toString();
        if (TIs.isNil(literal)) {
            /*
             * If content is null or empty
             * return to null reference for future usage
             */
            return null;
        } else {
            if (EmType.Yaml.ARRAY == type) {
                return (T) new JsonArray(literal);
            } else {
                return (T) new JsonObject(literal);
            }
        }
    }

    private static JsonNode getYamlNode(final String filename) {
        final InputStream in = IoStream.read(filename);
        final JsonNode node = HFn.failOr(() -> {
            if (null == in) {
                throw new EmptyIoException(Io.class, filename);
            }
            return YAML.readTree(in);
        });
        if (null == node) {
            throw new EmptyIoException(Io.class, filename);
        }
        return node;
    }

    /**
     * Check yaml type
     *
     * @param filename input file name
     *
     * @return Yaml of the file by format
     */
    private static EmType.Yaml getYamlType(final String filename) {
        final String content = ioString(filename, null);
        return HFn.runOr(EmType.Yaml.OBJECT, () -> {
            if (content.trim().startsWith(VString.DASH)) {
                return EmType.Yaml.ARRAY;
            } else {
                return EmType.Yaml.OBJECT;
            }
        }, content);
    }

    /**
     * Read to property object
     *
     * @param filename input filename
     *
     * @return Properties that will be returned
     */
    static Properties ioProp(final String filename) {
        return HFn.failOr(() -> {
            try (final InputStream in = IoStream.read(filename)) {
                final Properties prop = new Properties();
                prop.load(in);
                return prop;
            }
        }, filename);
    }

    /**
     * Read to URL
     *
     * @param filename input filename
     *
     * @return URL of this filename include ZIP/JAR url
     */
    static URL ioURL(final String filename) {
        return HFn.failOr(() -> {
            final URL url = Thread.currentThread().getContextClassLoader()
                .getResource(filename);
            return HFn.runOr(null == url, null,
                () -> Io.class.getResource(filename),
                () -> url);
        }, filename);
    }

    /**
     * Read to Buffer
     *
     * @param filename input filename
     *
     * @return Buffer from filename
     */
    @SuppressWarnings("all")
    static Buffer ioBuffer(final String filename) {
        final InputStream in = IoStream.read(filename);
        return HFn.failOr(() -> {
            final byte[] bytes = new byte[in.available()];
            in.read(bytes);
            in.close();
            return Buffer.buffer(bytes);
        }, in);
    }

    /**
     * Read to File
     *
     * @param filename input filename
     *
     * @return File object by filename that input
     */
    static File ioFile(final String filename) {
        return HFn.failOr(() -> {
            final File file = new File(filename);
            return HFn.runOr(file.exists(), null,
                () -> file,
                () -> {
                    final URL url = ioURL(filename);
                    if (null == url) {
                        throw new EmptyIoException(Io.class, filename);
                    }
                    return new File(url.getFile());
                });
        }, filename);
    }

    static boolean isExist(final String filename) {
        try {
            final File file = new File(filename);
            if (file.exists()) {
                return true;
            }
            final URL url = ioURL(filename);
            return Objects.nonNull(url);
        } catch (final Throwable ex) {
            // Fix: java.lang.NullPointerException
            // File does not exist
            return false;
        }
    }

    /**
     * Read to Path
     *
     * @param filename input filename
     *
     * @return file content that converted to String
     */
    static String ioPath(final String filename) {
        return HFn.failOr(() -> {
            final File file = ioFile(filename);
            return HFn.failOr(() -> {
                LOG.io(INFO.Io.INF_PATH, file.getAbsolutePath());
                return file.getAbsolutePath();
            }, file);
        }, filename);
    }

    static String ioCompress(final String file) {
        final byte[] bytes = IoStream.readBytes(file);
        final byte[] compressed = IoCompressor.decompress(bytes);
        return new String(compressed, VValue.DFT.CHARSET);
    }

    static Buffer zip(final Set<String> fileSet) {
        // Create Tpl zip file path
        return HFn.failOr(() -> {
            final ByteArrayOutputStream fos = new ByteArrayOutputStream();
            try (final ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(fos))) {
                final byte[] buffers = new byte[VValue.DFT.SIZE_BYTE_ARRAY];
                fileSet.forEach(filename -> zipWrite(zos, buffers, filename));
            }
            return Buffer.buffer(fos.toByteArray());
        });
    }

    @ChatGPT
    private static void zipWrite(final ZipOutputStream zos, final byte[] buffers, final String filename) {
        HFn.jvmAt(() -> {
            final File file = new File(filename);
            final ZipEntry zipEntry = new ZipEntry(file.getName());
            zos.putNextEntry(zipEntry);
            try (final FileInputStream fis = new FileInputStream(file);
                 final BufferedInputStream bis = new BufferedInputStream(fis, VValue.DFT.SIZE_BYTE_ARRAY)) {
                int read;
                while ((read = bis.read(buffers)) != -1) {
                    zos.write(buffers, 0, read);
                }
            }
        });
    }
}