com.stratio.deep.es.utils.UtilES.java Source code

Java tutorial

Introduction

Here is the source code for com.stratio.deep.es.utils.UtilES.java

Source

/*
 * Copyright 2014, Stratio.
 *
 * 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.stratio.deep.es.utils;

/**
 * Several utilities to work used in the Spark <=> ElasticSearch integration.
 */

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.hadoop.io.ArrayWritable;
import org.apache.hadoop.io.BooleanWritable;
import org.apache.hadoop.io.ByteWritable;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.FloatWritable;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
import org.elasticsearch.hadoop.mr.LinkedMapWritable;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.stratio.deep.commons.entity.Cell;
import com.stratio.deep.commons.entity.Cells;
import com.stratio.deep.commons.entity.IDeepType;
import com.stratio.deep.commons.filter.Filter;
import com.stratio.deep.commons.filter.FilterType;
import com.stratio.deep.commons.utils.AnnotationUtils;
import com.stratio.deep.commons.utils.Utils;

/**
 * Created by rcrespo on 29/07/14.
 */
public final class UtilES {

    private static final Logger LOG = LoggerFactory.getLogger(UtilES.class);

    /**
     * Private default constructor.
     */
    private UtilES() {
        throw new UnsupportedOperationException();
    }

    /**
     * converts from JSONObject to an entity class with deep's anotations
     *
     * @param classEntity the entity name.
     * @param jsonObject  the instance of the JSONObject to convert.
     * @param <T>         return type.
     * @return the provided JSONObject converted to an instance of T.
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws java.lang.reflect.InvocationTargetException
     */
    public static <T> T getObjectFromJson(Class<T> classEntity, LinkedMapWritable jsonObject)
            throws IllegalAccessException, InstantiationException, InvocationTargetException,
            NoSuchMethodException {
        T t = classEntity.newInstance();

        Field[] fields = AnnotationUtils.filterDeepFields(classEntity);

        Object insert;

        for (Field field : fields) {
            Method method = Utils.findSetter(field.getName(), classEntity, field.getType());

            Class<?> classField = field.getType();
            String key = AnnotationUtils.deepFieldName(field);
            Text text = new org.apache.hadoop.io.Text(key);
            Writable currentJson = jsonObject.get(text);
            if (currentJson != null) {

                if (Iterable.class.isAssignableFrom(classField)) {
                    Type type = field.getGenericType();
                    insert = subDocumentListCase(type, (ArrayWritable) currentJson);
                    method.invoke(t, (insert));

                } else if (IDeepType.class.isAssignableFrom(classField)) {
                    insert = getObjectFromJson(classField, (LinkedMapWritable) currentJson);
                    method.invoke(t, (insert));
                } else {
                    insert = currentJson;
                    try {
                        method.invoke(t, getObjectFromWritable((Writable) insert));
                    } catch (Exception e) {
                        LOG.error("impossible to convert field " + t + " :" + field + " error: " + e.getMessage());
                        method.invoke(t,
                                Utils.castNumberType(getObjectFromWritable((Writable) insert), t.getClass()));
                    }

                }

            }
        }

        return t;
    }

    private static <T> Object subDocumentListCase(Type type, ArrayWritable arrayWritable)
            throws IllegalAccessException, InstantiationException, InvocationTargetException,
            NoSuchMethodException {
        ParameterizedType listType = (ParameterizedType) type;

        Class<?> listClass = (Class<?>) listType.getActualTypeArguments()[0];

        List list = new ArrayList();
        Writable[] writetable = arrayWritable.get();

        for (int i = 0; i < writetable.length; i++) {
            list.add(getObjectFromJson(listClass, (LinkedMapWritable) writetable[i]));
        }

        return list;
    }

    /**
     * converts from an entity class with deep's anotations to JSONObject.
     *
     * @param t   an instance of an object of type T to convert to JSONObject.
     * @param <T> the type of the object to convert.
     * @return the provided object converted to JSONObject.
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws InvocationTargetException
     */
    public static <T> JSONObject getJsonFromObject(T t)
            throws IllegalAccessException, InstantiationException, InvocationTargetException {
        Field[] fields = AnnotationUtils.filterDeepFields(t.getClass());

        JSONObject json = new JSONObject();

        for (Field field : fields) {
            Method method = Utils.findGetter(field.getName(), t.getClass());
            Object object = method.invoke(t);
            if (object != null) {
                if (Collection.class.isAssignableFrom(field.getType())) {
                    Collection c = (Collection) object;
                    Iterator iterator = c.iterator();
                    List<JSONObject> innerJsonList = new ArrayList<>();

                    while (iterator.hasNext()) {
                        innerJsonList.add(getJsonFromObject((IDeepType) iterator.next()));
                    }
                    json.put(AnnotationUtils.deepFieldName(field), innerJsonList);
                } else if (IDeepType.class.isAssignableFrom(field.getType())) {
                    json.put(AnnotationUtils.deepFieldName(field), getJsonFromObject((IDeepType) object));
                } else {
                    json.put(AnnotationUtils.deepFieldName(field), object);
                }
            }
        }

        return json;
    }

    /**
     * converts from an entity class with deep's anotations to JSONObject.
     *
     * @param t   an instance of an object of type T to convert to JSONObject.
     * @param <T> the type of the object to convert.
     * @return the provided object converted to JSONObject.
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws InvocationTargetException
     */
    public static <T> LinkedMapWritable getLinkedMapWritableFromObject(T t)
            throws IllegalAccessException, InstantiationException, InvocationTargetException {
        Field[] fields = AnnotationUtils.filterDeepFields(t.getClass());

        LinkedMapWritable linkedMapWritable = new LinkedMapWritable();

        for (Field field : fields) {
            Method method = Utils.findGetter(field.getName(), t.getClass());
            Object object = method.invoke(t);
            if (object != null) {
                if (Collection.class.isAssignableFrom(field.getType())) {
                    Collection c = (Collection) object;
                    Iterator iterator = c.iterator();
                    List<LinkedMapWritable> innerJsonList = new ArrayList<>();

                    while (iterator.hasNext()) {
                        innerJsonList.add(getLinkedMapWritableFromObject((IDeepType) iterator.next()));
                    }
                    // linkedMapWritable.put(new Text(AnnotationUtils.deepFieldName(field)), new
                    // LinkedMapWritable[innerJsonList.size()]);
                } else if (IDeepType.class.isAssignableFrom(field.getType())) {
                    linkedMapWritable.put(new Text(AnnotationUtils.deepFieldName(field)),
                            getLinkedMapWritableFromObject((IDeepType) object));
                } else {
                    linkedMapWritable.put(new Text(AnnotationUtils.deepFieldName(field)),
                            getWritableFromObject(object));
                }
            }
        }

        return linkedMapWritable;
    }

    /**
     * returns the id value annotated with @DeepField(fieldName = "_id")
     *
     * @param t   an instance of an object of type T to convert to JSONObject.
     * @param <T> the type of the object to convert.
     * @return the provided object converted to Object.
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws InvocationTargetException
     */
    public static <T extends IDeepType> Object getId(T t)
            throws IllegalAccessException, InstantiationException, InvocationTargetException {
        // TODO : implement

        return null;
    }

    /**
     * converts from JSONObject to cell class
     *
     * @param jsonObject
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws InvocationTargetException
     */
    public static Cells getCellFromJson(LinkedMapWritable jsonObject, String tableName)
            throws IllegalAccessException, InstantiationException, InvocationTargetException,
            NoSuchMethodException {

        Cells cells = tableName != null ? new Cells(tableName) : new Cells();

        Set<Map.Entry<Writable, Writable>> entryJson = jsonObject.entrySet();

        for (Map.Entry<Writable, Writable> entry : entryJson) {

            if (LinkedMapWritable.class.isAssignableFrom(entry.getValue().getClass())) {
                Cells innerCells = getCellFromJson((LinkedMapWritable) entry.getValue(), null);
                cells.add(Cell.create(entry.getKey().toString(), innerCells));
            } else if (ArrayWritable.class.isAssignableFrom(entry.getValue().getClass())) {
                Writable[] writetable = ((ArrayWritable) entry.getValue()).get();
                List innerCell = new ArrayList<>();
                for (int i = 0; i < writetable.length; i++) {
                    if (writetable[i] instanceof LinkedMapWritable) {
                        innerCell.add(getCellFromJson((LinkedMapWritable) writetable[i], null));
                    } else {
                        innerCell.add(getObjectFromWritable(entry.getValue()));
                    }

                }
                cells.add(Cell.create(entry.getKey().toString(), innerCell));
            } else {

                cells.add(Cell.create(entry.getKey().toString(), getObjectFromWritable(entry.getValue())));
            }

        }
        return cells;
    }

    /**
     * Returns the object inside Writable
     *
     * @param writable
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException
     */
    private static Object getObjectFromWritable(Writable writable)
            throws IllegalAccessException, InstantiationException, InvocationTargetException {
        Object object = null;

        if (writable instanceof NullWritable) {
            object = NullWritable.get();
        } else if (writable instanceof BooleanWritable) {
            object = ((BooleanWritable) writable).get();
        } else if (writable instanceof Text) {
            object = writable.toString();
        } else if (writable instanceof ByteWritable) {
            object = ((ByteWritable) writable).get();
        } else if (writable instanceof IntWritable) {
            object = ((IntWritable) writable).get();
        } else if (writable instanceof LongWritable) {
            object = ((LongWritable) writable).get();
        } else if (writable instanceof BytesWritable) {
            object = ((BytesWritable) writable).getBytes();
        } else if (writable instanceof DoubleWritable) {
            object = ((DoubleWritable) writable).get();
        } else if (writable instanceof FloatWritable) {
            object = ((FloatWritable) writable).get();
        } else {
            // TODO : do nothing
        }

        return object;
    }

    /**
     * Returns the object inside Writable
     *
     * @param object
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException
     */
    private static Writable getWritableFromObject(Object object) {

        Writable writable = null;

        if (object instanceof String) {

            writable = new Text(object.toString());

        } else if (object instanceof Long) {

            writable = new LongWritable((Long) object);

        } else {

            writable = new IntWritable((Integer) object);

        }
        // writable = writable!=null?writable:new Text("");
        return writable;
    }

    /**
     * converts from cell class to JSONObject
     *
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws InvocationTargetException
     */
    public static JSONObject getJsonFromCell(Cells cells)
            throws IllegalAccessException, InstantiationException, InvocationTargetException {

        JSONObject json = new JSONObject();
        for (Cell cell : cells) {
            if (cell.getCellValue() != null) {
                if (Collection.class.isAssignableFrom(cell.getCellValue().getClass())) {
                    Collection c = (Collection) cell.getCellValue();
                    Iterator iterator = c.iterator();
                    List<JSONObject> innerJsonList = new ArrayList<>();

                    while (iterator.hasNext()) {
                        innerJsonList.add(getJsonFromCell((Cells) iterator.next()));
                    }
                    json.put(cell.getCellName(), innerJsonList);
                } else if (Cells.class.isAssignableFrom(cell.getCellValue().getClass())) {
                    json.put(cell.getCellName(), getJsonFromCell((Cells) cell.getCellValue()));
                } else {
                    json.put(cell.getCellName(), cell.getCellValue());
                }

            }
        }

        return json;
    }

    public static QueryBuilder generateQuery(Filter... filterArray) {
        List<Filter> range = new ArrayList<>();
        List<Filter> ne = new ArrayList<>();
        List<Filter> is = new ArrayList<>();
        BoolQueryBuilder qb = QueryBuilders.boolQuery();

        for (Filter filter : filterArray) {
            if (!filter.getFilterType().equals(FilterType.EQ) && !filter.getFilterType().equals(FilterType.NEQ)) {
                range.add(filter);
            } else if (filter.getFilterType().equals(FilterType.EQ)) {
                is.add(filter);
            } else {
                ne.add(filter);
            }
        }

        for (Filter filter : range) {

            RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(filter.getField());
            switch (filter.getFilterType()) {
            case LT:
                rangeQueryBuilder.lt(filter.getValue());
                break;
            case LTE:
                rangeQueryBuilder.lte(filter.getValue());
                break;
            case GT:
                rangeQueryBuilder.gt(filter.getValue());
                break;
            case GTE:
                rangeQueryBuilder.gte(filter.getValue());
                break;
            default:
                break;
            }
            qb.must(rangeQueryBuilder);
        }

        for (Filter filter : is) {
            qb.must(QueryBuilders.matchQuery(filter.getField(), filter.getValue()));
        }

        for (Filter filter : ne) {
            qb.mustNot(QueryBuilders.matchQuery(filter.getField(), filter.getValue()));
        }
        return qb;
    }

}