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

org.elasticsearch.hadoop.serialization.builder.JdkValueWriter Maven / Gradle / Ivy

/*
 * Licensed to Elasticsearch under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.hadoop.serialization.builder;

import org.elasticsearch.hadoop.serialization.Generator;
import org.elasticsearch.hadoop.util.ObjectUtils;

import javax.xml.bind.DatatypeConverter;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Value writer for JDK types.
 */
public class JdkValueWriter extends FilteringValueWriter {

    protected final boolean writeUnknownTypes;

    public JdkValueWriter() {
        writeUnknownTypes = false;
    }

    public JdkValueWriter(boolean writeUnknownTypes) {
        this.writeUnknownTypes = writeUnknownTypes;
    }

    @Override
    public Result write(Object value, Generator generator) {
        return doWrite(value, generator, null);
    }

    protected Result doWrite(Object value, Generator generator, String parentField) {
        if (value == null) {
            generator.writeNull();
        }
        else if (value instanceof String) {
            generator.writeString((String) value);
        }
        else if (value instanceof Integer) {
            generator.writeNumber(((Integer) value).intValue());
        }
        else if (value instanceof Long) {
            generator.writeNumber(((Long) value).longValue());
        }
        else if (value instanceof Float) {
            generator.writeNumber(((Float) value).floatValue());
        }
        else if (value instanceof Double) {
            generator.writeNumber(((Double) value).doubleValue());
        }
        else if (value instanceof Short) {
            generator.writeNumber(((Short) value).shortValue());
        }
        else if (value instanceof Byte) {
            generator.writeNumber(((Byte) value).byteValue());
        }
        // Big Decimal/Integer
        else if (value instanceof Number) {
            // check double vs long
            Number n = ((Number) value);
            double d = n.doubleValue();
            if (Math.floor(d) == d) {
                generator.writeNumber(n.longValue());
            }
            else {
                generator.writeNumber(d);
            }
        }
        else if (value instanceof Boolean) {
            generator.writeBoolean(((Boolean) value).booleanValue());
        }
        else if (value instanceof byte[]) {
            generator.writeBinary((byte[]) value);
        }
        else if (value.getClass().isArray()) {
            generator.writeBeginArray();
            for (Object o : ObjectUtils.toObjectArray(value)) {
                Result result = doWrite(o, generator, parentField);
                if (!result.isSuccesful()) {
                    return result;
                }
            }
            generator.writeEndArray();
        }
        else if (value instanceof Map) {
            generator.writeBeginObject();
            for (Entry entry : ((Map) value).entrySet()) {
                String fieldName = entry.getKey().toString();
                // filter out fields
                if (shouldKeep(parentField, fieldName)) {
                    generator.writeFieldName(fieldName);
                    Result result = doWrite(entry.getValue(), generator, fieldName);
                    if (!result.isSuccesful()) {
                        return result;
                    }
                }
            }
            generator.writeEndObject();
        }
        else if (value instanceof Iterable) {
            generator.writeBeginArray();
            for (Object o : (Iterable) value) {
                Result result = doWrite(o, generator, parentField);
                if (!result.isSuccesful()) {
                    return result;
                }
            }
            generator.writeEndArray();
        }
        else if (value instanceof Timestamp) {
            Timestamp timestamp = (Timestamp) value;
            long epochSeconds = timestamp.getTime() / 1000; // Getting rid of millisconds because they're captured in timestamp.getNanos()
            Instant instant = Instant.ofEpochSecond(epochSeconds, timestamp.getNanos());
            OffsetDateTime offsetDateTime = OffsetDateTime.ofInstant(instant, ZoneId.systemDefault());
            generator.writeString(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(offsetDateTime));
        }
        else if (value instanceof Date) {
            Calendar cal = Calendar.getInstance();
            cal.setTime((Date) value);
            generator.writeString(DatatypeConverter.printDateTime(cal));
        }
        else if (value instanceof Calendar) {
            generator.writeString(DatatypeConverter.printDateTime((Calendar) value));
        }
        else {
            if (writeUnknownTypes) {
                return handleUnknown(value, generator);
            }
            return Result.FAILED(value);
        }
        return Result.SUCCESFUL();
    }

    protected Result handleUnknown(Object value, Generator generator) {
        generator.writeString(value.toString());
        return Result.SUCCESFUL();
    }
}