com.bosscs.spark.commons.utils.Utils.java Source code

Java tutorial

Introduction

Here is the source code for com.bosscs.spark.commons.utils.Utils.java

Source

/*
 * Copyright 2016, Jerry Xiong, BOSSCS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.bosscs.spark.commons.utils;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang.StringUtils;

import com.bosscs.spark.commons.config.BaseConfig;
import com.bosscs.spark.commons.config.JobConfig;
import com.bosscs.spark.commons.config.ExtractorConfig;
import com.bosscs.spark.commons.entity.Cell;
import com.bosscs.spark.commons.entity.Cells;
import com.bosscs.spark.commons.entity.IType;
import com.bosscs.spark.commons.exception.ExtractorInitializationException;
import com.bosscs.spark.commons.exception.GenericException;
import com.bosscs.spark.commons.exception.HadoopIOException;
import com.bosscs.spark.commons.rdd.IExtractor;

import org.apache.log4j.Logger;
import scala.Tuple2;

/**
 * Utility class providing useful methods to manipulate the conversion
 * between ByteBuffers maps coming from the underlying Cassandra API to
 * instances of a concrete javabean.
 *
 * @author Jerry Xiong
 */
public final class Utils {

    /**
     * The Log.
     */
    private static transient final Logger LOG = Logger.getLogger(Utils.class);

    /**
     * Creates a new instance of the given class.
     *
     * @param <T>   the type parameter
     * @param clazz the class object for which a new instance should be created.
     * @return the new instance of class clazz.
     */
    public static <T extends IType> T newTypeInstance(Class<T> clazz) {
        try {
            return clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new GenericException(e);
        }
    }

    /**
     * Creates a new instance of the given class name.
     *
     * @param <T>         the type parameter
     * @param className   the class object for which a new instance should be created.
     * @param returnClass the return class
     * @return the new instance of class clazz.
     */
    @SuppressWarnings("unchecked")
    public static <T> T newTypeInstance(String className, Class<T> returnClass) {
        try {
            Class<T> clazz = (Class<T>) Class.forName(className);
            return clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
            throw new GenericException(e);
        }
    }

    /**
     * Quoting for working with uppercase
     *
     * @param identifier the identifier
     * @return the string
     */
    public static String quote(String identifier) {
        if (StringUtils.isEmpty(identifier)) {
            return identifier;
        }

        String res = identifier.trim();

        if (!res.startsWith("\"")) {
            res = "\"" + res;
        }

        if (!res.endsWith("\"")) {
            res = res + "\"";
        }

        return res;

    }

    /**
     * Quoting for working with uppercase
     *
     * @param identifier the identifier
     * @return the string
     */
    public static String singleQuote(String identifier) {
        if (StringUtils.isEmpty(identifier)) {
            return identifier;
        }

        String res = identifier.trim();

        if (!res.startsWith("'")) {
            res = "'" + res;
        }

        if (!res.endsWith("'")) {
            res = res + "'";
        }

        return res;
    }

    /**
     * Returns a CQL batch query wrapping the given statements.
     *
     * @param statements the list of statements to use to generate the batch statement.
     * @return the batch statement.
     */
    public static String batchQueryGenerator(List<String> statements) {
        StringBuilder sb = new StringBuilder("BEGIN BATCH \n");

        for (String statement : statements) {
            sb.append(statement).append("\n");
        }

        sb.append(" APPLY BATCH;");

        return sb.toString();
    }

    /**
     * Splits columns names and values as required by Datastax java driver to generate an Insert query.
     *
     * @param tuple an object containing the key Cell(s) as the first element and all the other columns as the second element.
     * @return an object containing an array of column names as the first element and an array of column values as the second element.
     */
    public static Tuple2<String[], Object[]> prepareTuple4CqlDriver(Tuple2<Cells, Cells> tuple) {
        Cells keys = tuple._1();
        Cells columns = tuple._2();

        String[] names = new String[keys.size() + columns.size()];
        Object[] values = new Object[keys.size() + columns.size()];

        for (int k = 0; k < keys.size(); k++) {
            Cell cell = keys.getCellByIdx(k);

            names[k] = quote(cell.getCellName());
            values[k] = cell.getCellValue();
        }

        for (int v = keys.size(); v < (keys.size() + columns.size()); v++) {
            Cell cell = columns.getCellByIdx(v - keys.size());

            names[v] = quote(cell.getCellName());
            values[v] = cell.getCellValue();
        }

        return new Tuple2<>(names, values);
    }

    /**
     * Resolves the setter name for the property whose name is 'propertyName' whose type is 'valueType'
     * in the entity bean whose class is 'entityClass'.
     * If we don't find a setter following Java's naming conventions, before throwing an exception we try to
     * resolve the setter following Scala's naming conventions.
     *
     * @param propertyName the field name of the property whose setter we want to resolve.
     * @param entityClass  the bean class object in which we want to search for the setter.
     * @param valueType    the class type of the object that we want to pass to the setter.
     * @return the resolved setter.
     */
    @SuppressWarnings("unchecked")
    public static Method findSetter(String propertyName, Class entityClass, Class valueType) {
        Method setter;
        String setterName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);

        try {
            setter = entityClass.getMethod(setterName, valueType);
        } catch (NoSuchMethodException e) {
            // let's try with scala setter name
            try {
                setter = entityClass.getMethod(propertyName + "_$eq", valueType);
            } catch (NoSuchMethodException e1) {
                throw new HadoopIOException(e1);
            }
        }

        return setter;
    }

    /**
     * @param object
     * @param fieldName
     * @param fieldValue
     * @return if the operation has been correct.
     */
    public static boolean setFieldWithReflection(Object object, String fieldName, Object fieldValue) {
        Class<?> clazz = object.getClass();
        while (clazz != null) {
            try {
                Field field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                field.set(object, fieldValue);
                return true;
            } catch (NoSuchFieldException e) {
                clazz = clazz.getSuperclass();
            } catch (Exception e) {
                throw new IllegalStateException(e);
            }
        }
        return false;
    }

    /**
     * Resolves the getter name for the property whose name is 'propertyName' whose type is 'valueType'
     * in the entity bean whose class is 'entityClass'.
     * If we don't find a setter following Java's naming conventions, before throwing an exception we try to
     * resolve the setter following Scala's naming conventions.
     *
     * @param propertyName the field name of the property whose getter we want to resolve.
     * @param entityClass  the bean class object in which we want to search for the getter.
     * @return the resolved getter.
     */
    @SuppressWarnings("unchecked")
    public static Method findGetter(String propertyName, Class entityClass) {
        Method getter;

        String getterName = "get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
        try {
            getter = entityClass.getMethod(getterName);
        } catch (NoSuchMethodException e) {
            // let's try with scala setter name
            try {
                getter = entityClass.getMethod(propertyName + "_$eq");
            } catch (NoSuchMethodException e1) {
                throw new HadoopIOException(e1);
            }
        }

        return getter;
    }

    /**
     * Returns the inet address for the specified location.
     *
     * @param location the address as String
     * @return the InetAddress object associated to the provided address.
     */
    public static InetAddress inetAddressFromLocation(String location) {
        try {
            return InetAddress.getByName(location);
        } catch (UnknownHostException e) {
            throw new HadoopIOException(e);
        }
    }

    /**
     * Return the set of fields declared at all level of class hierachy
     *
     * @param clazz the clazz
     * @return the field [ ]
     */
    public static Field[] getAllFields(Class clazz) {
        return getAllFieldsRec(clazz, new ArrayList<Field>());
    }

    /**
     * Get all fields rec.
     *
     * @param clazz  the clazz
     * @param fields the fields
     * @return the field [ ]
     */
    private static Field[] getAllFieldsRec(Class clazz, List<Field> fields) {
        Class superClazz = clazz.getSuperclass();
        if (superClazz != null) {
            getAllFieldsRec(superClazz, fields);
        }

        fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
        return fields.toArray(new Field[fields.size()]);
    }

    /**
     * private constructor.
     */
    private Utils() {

    }

    /**
     * Remove address port.
     *
     * @param stringList the string list
     * @return the list
     */
    public static List<String> removeAddressPort(List<String> stringList) {
        List<String> adresNoPort = new ArrayList<>();

        for (String s : stringList) {
            int index = s.indexOf(":");
            if (index > -1) {
                adresNoPort.add(s.substring(0, index));
                continue;
            }
            adresNoPort.add(s);

        }
        return adresNoPort;
    }

    /**
     * Split list by comma.
     *
     * @param hosts the hosts
     * @return string
     */
    public static String splitListByComma(List<String> hosts) {
        boolean firstHost = true;
        StringBuilder hostConnection = new StringBuilder();
        for (String host : hosts) {
            if (!firstHost) {
                hostConnection.append(",");
            }
            hostConnection.append(host.trim());
            firstHost = false;
        }
        return hostConnection.toString();
    }

    /**
     * Gets extractor instance.
     *
     * @param config the config
     * @return the extractor instance
     */
    public static <T, S extends BaseConfig> IExtractor<T, S> getExtractorInstance(S config) {

        try {
            Class<T> rdd = (Class<T>) config.getExtractorImplClass();
            if (rdd == null) {
                rdd = (Class<T>) Class.forName(config.getExtractorImplClassName());
            }
            Constructor<T> c;
            if (config.getEntityClass().isAssignableFrom(Cells.class)) {
                c = rdd.getConstructor();
                return (IExtractor<T, S>) c.newInstance();
            } else {
                c = rdd.getConstructor(Class.class);
                return (IExtractor<T, S>) c.newInstance(config.getEntityClass());
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException
                | InvocationTargetException | NoSuchMethodException | SecurityException e) {
            String message = "A exception happens and we wrap with DeepExtractorInitializationException"
                    + e.getMessage();
            LOG.error(message);
            throw new ExtractorInitializationException(message, e);
        }

    }

    /**
     * Cast number type.
     *
     * @param object the object
     * @param clazz  the clazz
     * @return object
     */
    public static Object castNumberType(Object object, Class clazz) {

        if (Number.class.isAssignableFrom(clazz)) {
            //            AtomicInteger, AtomicLong, BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, Short
            if (Double.class.isAssignableFrom(clazz)) {
                return ((Number) object).doubleValue();
            } else if (Long.class.isAssignableFrom(clazz)) {
                return ((Number) object).longValue();

            } else if (Float.class.isAssignableFrom(clazz)) {
                return ((Number) object).floatValue();

            } else if (Integer.class.isAssignableFrom(clazz)) {
                return ((Number) object).intValue();

            } else if (Short.class.isAssignableFrom(clazz)) {
                return ((Number) object).shortValue();

            } else if (Byte.class.isAssignableFrom(clazz)) {
                return ((Number) object).byteValue();

            } else if (BigInteger.class.isAssignableFrom(clazz)) {
                return BigInteger.valueOf(((Number) object).longValue());

            } else if (BigDecimal.class.isAssignableFrom(clazz)) {
                return BigDecimal.valueOf(((Number) object).longValue());

            } else if (AtomicLong.class.isAssignableFrom(clazz)) {
                return new AtomicLong(((Number) object).longValue());

            } else if (AtomicInteger.class.isAssignableFrom(clazz)) {
                return new AtomicInteger(((Number) object).intValue());
            }
        }
        throw new ClassCastException("it is not a Number Type" + object.getClass() + "|" + clazz);
    }

    public static Object castingUtil(String value, Class classCasting) {
        Object object = value;

        //Numeric
        if (Number.class.isAssignableFrom(classCasting)) {
            if (classCasting.isAssignableFrom(Double.class)) {
                return Double.valueOf(value);
            } else if (classCasting.isAssignableFrom(Long.class)) {
                return Long.valueOf(value);

            } else if (classCasting.isAssignableFrom(Float.class)) {
                return Float.valueOf(value);

            } else if (classCasting.isAssignableFrom(Integer.class)) {
                return Integer.valueOf(value);

            } else if (classCasting.isAssignableFrom(Short.class)) {
                return Short.valueOf(value);

            } else if (classCasting.isAssignableFrom(Byte.class)) {
                return Byte.valueOf(value);
            }
        } else if (String.class.isAssignableFrom(classCasting)) {
            return object.toString();
        }
        //Class not recognise yet
        return null;

    }

    public static <S extends BaseConfig, W extends JobConfig> W initConfig(S config, W deepJobConfig) {
        if (config instanceof ExtractorConfig) {
            deepJobConfig.initialize((ExtractorConfig) config);
        } else if (deepJobConfig.getClass().isAssignableFrom(config.getClass())) {
            deepJobConfig = (W) ((W) config).initialize();
        } else {
            deepJobConfig.initialize((JobConfig) config);
        }
        return deepJobConfig;

    }

    /**
     * Returns an instance clone.
     * this method gets every class property by reflection, including its parents properties
     * @param t
     * @param <T>
     * @return T object.
     */
    public static <T> T cloneObjectWithParents(T t) throws IllegalAccessException, InstantiationException {
        T clone = (T) t.getClass().newInstance();

        List<Field> allFields = new ArrayList<>();

        Class parentClass = t.getClass().getSuperclass();

        while (parentClass != null) {
            Collections.addAll(allFields, parentClass.getDeclaredFields());
            parentClass = parentClass.getSuperclass();
        }

        Collections.addAll(allFields, t.getClass().getDeclaredFields());

        for (Field field : allFields) {
            int modifiers = field.getModifiers();
            //We skip final and static fields
            if ((Modifier.FINAL & modifiers) != 0 || (Modifier.STATIC & modifiers) != 0) {
                continue;
            }
            field.setAccessible(true);

            Object value = field.get(t);

            if (Collection.class.isAssignableFrom(field.getType())) {
                Collection collection = (Collection) field.get(clone);
                if (collection == null) {
                    collection = (Collection) field.get(t).getClass().newInstance();
                }
                collection.addAll((Collection) field.get(t));
                value = collection;
            } else if (Map.class.isAssignableFrom(field.getType())) {
                Map clonMap = (Map) field.get(t).getClass().newInstance();
                clonMap.putAll((Map) field.get(t));
                value = clonMap;
            }
            field.set(clone, value);
        }

        return clone;
    }

    /**
     * Returns an instance of ThreadPoolExecutor using an bounded queue and blocking when the worker queue is full.
     * @param nThreads thread pool size
     * @param queueSize workers queue size
     * @return thread pool executor
     */
    public static ExecutorService newBlockingFixedThreadPoolExecutor(int nThreads, int queueSize) {
        BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(queueSize);
        RejectedExecutionHandler blockingRejectedExecutionHandler = new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable task, ThreadPoolExecutor executor) {
                try {
                    executor.getQueue().put(task);
                } catch (InterruptedException e) {
                }
            }

        };

        return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, blockingQueue,
                blockingRejectedExecutionHandler);
    }
}