All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.ngoanh2n.Commons Maven / Gradle / Ivy

There is a newer version: 1.7.0
Show newest version
package com.github.ngoanh2n;

import com.google.errorprone.annotations.CanIgnoreReturnValue;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.mozilla.universalchardet.UniversalDetector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Common helpers.
 *
 * @author Ho Huu Ngoan ([email protected])
 */
@SuppressWarnings({"unchecked", "ResultOfMethodCallIgnored"})
@CanIgnoreReturnValue
public final class Commons {
    private static final Logger log = LoggerFactory.getLogger(Commons.class);

    private Commons() { /* No implementation necessary */ }

    //-------------------------------------------------------------------------------//

    /**
     * Creates a timestamp.
     *
     * @return timestamp as string.
     */
    public static String timestamp() {
        Format dateFormat = new SimpleDateFormat("yyyyMMdd.HHmmss.SSS");
        return dateFormat.format(new Date());
    }

    /**
     * Creates recursively directory from {@linkplain File}.
     *
     * @param file is directory as File.
     * @return directory as a file.
     */
    public static File createDir(@Nonnull File file) {
        return createDir(file.toPath()).toFile();
    }

    /**
     * Creates recursively directory from {@linkplain Path}.
     *
     * @param path is directory as Path.
     * @return directory as a path.
     */
    public static Path createDir(@Nonnull Path path) {
        Iterator elements = path.iterator();
        Path parentElement = Paths.get("");

        while (elements.hasNext()) {
            parentElement = parentElement.resolve(elements.next());
            parentElement.toFile().mkdirs();
        }
        return path;
    }

    /**
     * Gets relative path of file against to current user directory.
     *
     * @param file to get relative path.
     * @return relative path.
     */
    public static File getRelative(@Nonnull File file) {
        return getRelative(file.toPath()).toFile();
    }

    /**
     * Gets relative path of path against to current user directory.
     *
     * @param path to get relative path.
     * @return relative path.
     */
    public static Path getRelative(@Nonnull Path path) {
        String userDir = System.getProperty("user.dir");
        Path userPath = Paths.get(userDir);
        try {
            return userPath.relativize(path);
        } catch (IllegalArgumentException ignored) {
            return path;
        }
    }

    /**
     * Writes {@linkplain Properties} to file.
     *
     * @param file  to be stored.
     * @param props to be written.
     * @return output file.
     */
    public static File writeProps(Properties props, File file) {
        createDir(file.toPath());
        String msg = String.format("Write Properties to %s", getRelative(file));

        try (OutputStream os = Files.newOutputStream(file.toPath())) {
            props.store(os, null);
        } catch (IOException e) {
            log.error(msg);
            throw new RuntimeError(msg, e);
        }
        log.debug(msg);
        return file;
    }

    /**
     * Reads {@linkplain Properties} from given Java resource name.
     *
     * @param resourceName Java resource name to read.
     * @return {@linkplain Properties} object.
     */
    public static Properties readProps(@Nonnull String resourceName) {
        File file = Resource.getFile(resourceName);
        return readProps(file, "UTF-8");
    }

    /**
     * Reads {@linkplain Properties} from given properties file.
     *
     * @param file    to read.
     * @param charset The name of a supported charset.
     * @return {@linkplain Properties} object.
     */
    public static Properties readProps(@Nonnull File file, String charset) {
        Properties props = new Properties();
        String path = getRelative(file).getPath().replace('\\', '/');
        String msg = "Read Properties " + path;

        try (InputStream is = Files.newInputStream(file.toPath())) {
            InputStreamReader isr = new InputStreamReader(is, charset);
            props.load(isr);
        } catch (IOException e) {
            log.error(msg);
            throw new RuntimeError(msg, e);
        }
        log.debug(msg);
        return props;
    }

    /**
     * Gets the charset of a file. 
* Method to mark {@linkplain UniversalDetector} for reusing. * * @param file The file to check charset for. * @return The charset of the file, null when could not be determined. * @throws IOException if some IO error occurs. */ public static String detectCharset(File file) throws IOException { return UniversalDetector.detectCharset(file.toPath()); } /** * Reads value of the {@link Field}. Its parents will be considered.
*
    *
  • {@code private Type aField} *
  • {@code private final Type aField} *
* * @param Type of result will be returned. * @param target The object instance to reflect, must not be {@code null}. * @param name The field name to obtain. * @return The field value. */ public static T readField(Object target, String name) { String msg = msgFieldAccess(target.getClass(), name, "Read"); Field[] fields = FieldUtils.getAllFields(target.getClass()); for (Field field : fields) { if (field.getName().equals(name)) { field.setAccessible(true); try { return (T) field.get(target); } catch (IllegalAccessException e) { log.error(msg); throw new RuntimeError(msg, e); } } } log.error(msg); throw new RuntimeError(msg); } /** * Reads value of the {@link Field}. Its parents will be considered.
*
    *
  • {@code private static final Type aField} *
* * @param Type of result will be returned. * @param target The object class to reflect, must not be {@code null}. * @param name The field name to obtain. * @return The field value. */ public static T readField(Class target, String name) { String msg = msgFieldAccess(target, name, "Read"); Field[] fields = FieldUtils.getAllFields(target); for (Field field : fields) { if (field.getName().equals(name)) { field.setAccessible(true); try { return (T) field.get(target); } catch (IllegalAccessException e) { log.error(msg); throw new RuntimeError(msg, e); } } } log.error(msg); throw new RuntimeError(msg); } /** * Writes value to the field with modifiers: *
    *
  • Target object has fields:
         *         {@code private Type aField}
         *         {@code private final Type aField}
    *
  • Target object's parents have fields:
         *         {@code private Type aField}
         *         {@code private final Type aField}
         *         {@code private static Type aField}
         *         {@code private static final Type aField}
    *
* * @param target The object instance to reflect, must not be {@code null}. * @param name The field name to obtain. * @param value The new value for the field of object being modified. */ public static void writeField(Object target, String name, Object value) { String msg = msgFieldAccess(target.getClass(), name, "Write"); List fieldList = Arrays.stream(FieldUtils.getAllFields(target.getClass())) .filter(field -> field.getName().equals(name)) .collect(Collectors.toList()); for (Field field : fieldList) { field.setAccessible(true); try { if (!Modifier.isStatic(field.getModifiers())) { Object fValue = field.get(target); if (fValue.hashCode() != value.hashCode()) { field.set(target, value); } } else { Field modifiers = FieldUtils.getField(Field.class, "modifiers", true); modifiers.setAccessible(true); modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); field.set(null, value); } } catch (IllegalAccessException e) { log.error(msg); throw new RuntimeError(msg, e); } } } /** * Writes value to the field with modifiers: *
    *
  • Target object has fields:
         *         {@code private static Type aField}
         *         {@code private static final Type aField}
    *
  • Target object's parents have fields:
         *         {@code private static Type aField}
         *         {@code private static final Type aField}
    *
* * @param target The object class to reflect, must not be {@code null}. * @param name The field name to obtain. * @param value The new value for the field of object being modified. */ public static void writeField(Class target, String name, Object value) { String msg = msgFieldAccess(target, name, "Write"); List fields = Arrays.stream(FieldUtils.getAllFields(target)) .filter(field -> field.getName().equals(name)) .collect(Collectors.toList()); for (Field field : fields) { field.setAccessible(true); try { if (!Modifier.isStatic(field.getModifiers())) { boolean override = readField(field, "override"); if (!override) { Object fValue = field.get(target); if (fValue.hashCode() != value.hashCode()) { field.set(target, value); } } } else { Field modifiers = FieldUtils.getField(Field.class, "modifiers", true); modifiers.setAccessible(true); modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); field.set(null, value); } } catch (IllegalAccessException e) { log.error(msg); throw new RuntimeError(msg, e); } } } /** * Convert String value to a specific object. * * @param type The Class object which to return an object. * @param value String value to convert. * @param The type of target object. * @return The target object. */ public static T convertValue(Class type, String value) { if (!type.isEnum()) { if (type == URL.class) { try { return (T) new URL(value); } catch (Exception e) { throw new RuntimeError(e); } } if (type == String.class) return (T) value; if (type == Byte.class) return (T) Byte.valueOf(value); if (type == Long.class) return (T) Long.valueOf(value); if (type == Short.class) return (T) Short.valueOf(value); if (type == Float.class) return (T) Float.valueOf(value); if (type == Double.class) return (T) Double.valueOf(value); if (type == Integer.class) return (T) Integer.valueOf(value); if (type == Boolean.class) return (T) Boolean.valueOf(value); throw new RuntimeError("Type " + type.getTypeName() + " cannot be parsed"); } return Commons.buildEnum(type, value).orElse(null); } /** * Builds enum from enum class and enum constant name. * * @param type The Class object of the enum type from which to return a constant. * @param name The name of enum constant to return, exactly as declared in its enum declaration. * @param The type of enum object. * @return Optional of the enum constant of the specified enum type with the specified name. */ @SuppressWarnings("unchecked") public static Optional buildEnum(Class type, String name) { for (Field field : type.getDeclaredFields()) { if (field.isEnumConstant() && field.getName().equals(name)) { try { Method valueOfMethod = type.getDeclaredMethod("valueOf", String.class); return (Optional) Optional.of(valueOfMethod.invoke(null, name)); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { return Optional.empty(); } } } return Optional.empty(); } //-------------------------------------------------------------------------------// private static String msgFieldAccess(Class target, String name, String action) { return String.format("%s field %s.%s", action, target.getName(), name); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy