Package com.asakusafw.directio.hive.parquet

Source Code of com.asakusafw.directio.hive.parquet.AbstractIntConverter

/**
* Copyright 2011-2014 Asakusa Framework Team.
*
* 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.asakusafw.directio.hive.parquet;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import parquet.column.Dictionary;
import parquet.io.api.Binary;
import parquet.io.api.RecordConsumer;
import parquet.schema.OriginalType;
import parquet.schema.PrimitiveType;
import parquet.schema.PrimitiveType.PrimitiveTypeName;
import parquet.schema.Type;
import parquet.schema.Type.Repetition;

import com.asakusafw.directio.hive.util.TemporalUtil;
import com.asakusafw.runtime.value.DateOption;
import com.asakusafw.runtime.value.DateTimeOption;
import com.asakusafw.runtime.value.DecimalOption;
import com.asakusafw.runtime.value.ValueOption;

/**
* Converts between {@link ValueOption} and {@code string (binary)}.
* @since 0.7.0
*/
public enum StringValueDrivers implements ParquetValueDriver {

    /**
     * {@link DecimalOption}.
     */
    DECIMAL(DecimalOption.class) {
        @Override
        public ValueConverter getConverter() {
            return new ToDecimalOption();
        }
        @Override
        public ValueWriter getWriter() {
            return new FromDecimalOption();
        }
    },

    /**
     * {@link DateOption}.
     */
    DATE(DateOption.class) {
        @Override
        public ValueConverter getConverter() {
            return new ToDateOption();
        }
        @Override
        public ValueWriter getWriter() {
            return new FromDateOption();
        }
    },

    /**
     * {@link DateTimeOption}.
     */
    DATETIME(DateTimeOption.class) {
        @Override
        public ValueConverter getConverter() {
            return new ToDateTimeOption();
        }
        @Override
        public ValueWriter getWriter() {
            return new FromDateTimeOption();
        }
    },
    ;

    final Class<? extends ValueOption<?>> valueOptionClass;

    private StringValueDrivers(Class<? extends ValueOption<?>> valueOptionClass) {
        this.valueOptionClass = valueOptionClass;
    }

    @Override
    public Type getType(String name) {
        return new PrimitiveType(Repetition.OPTIONAL, PrimitiveTypeName.BINARY, name, OriginalType.UTF8);
    }

    /**
     * Returns a {@link ParquetValueDriver} for the specified type.
     * @param valueClass the {@link ValueOption} type
     * @return the corresponded {@link ParquetValueDriver}, or {@code null} if it is not found
     */
    public static ParquetValueDriver find(Class<?> valueClass) {
        return Lazy.FROM_CLASS.get(valueClass);
    }

    private static final class Lazy {

        static final Map<Class<?>, StringValueDrivers> FROM_CLASS;
        static {
            Map<Class<?>, StringValueDrivers> map = new HashMap<Class<?>, StringValueDrivers>();
            for (StringValueDrivers element : StringValueDrivers.values()) {
                map.put(element.valueOptionClass, element);
            }
            FROM_CLASS = map;
        }

        private Lazy() {
            return;
        }
    }

    abstract static class AbstractWriter implements ValueWriter {

        protected abstract String toString(Object value);

        @Override
        public void write(Object value, RecordConsumer consumer) {
            consumer.addBinary(Binary.fromString(toString(value)));
        }
    }

    abstract static class AbstractConverter<T> extends ValueConverter {

        private T[] dict;

        protected AbstractConverter() {
            return;
        }

        protected abstract T parse(String value);

        protected abstract void drive(T value);

        @Override
        public boolean hasDictionarySupport() {
            return true;
        }

        @Override
        public void setDictionary(Dictionary dictionary) {
            T[] buf = prepareDictionaryBuffer(dictionary);
            for (int id = 0, max = dictionary.getMaxId(); id <= max; id++) {
                buf[id] = parse(dictionary.decodeToBinary(id).toStringUsingUTF8());
            }
        }

        @Override
        public void addValueFromDictionary(int dictionaryId) {
            drive(dict[dictionaryId]);
        }

        @Override
        public void addBinary(Binary value) {
            drive(parse(value.toStringUsingUTF8()));
        }

        @SuppressWarnings("unchecked")
        private T[] prepareDictionaryBuffer(Dictionary dictionary) {
            int size = dictionary.getMaxId() + 1;
            if (this.dict == null || this.dict.length < size) {
                int capacity = (int) (size * 1.2) + 1;
                this.dict = (T[]) new Object[capacity];
            } else {
                Arrays.fill(this.dict, null);
            }
            return this.dict;
        }
    }

    abstract static class AbstractIntConverter extends ValueConverter {

        private int[] dict;

        protected AbstractIntConverter() {
            return;
        }

        protected abstract int parse(String value);

        protected abstract void drive(int value);

        @Override
        public boolean hasDictionarySupport() {
            return true;
        }

        @Override
        public void setDictionary(Dictionary dictionary) {
            int[] buf = prepareDictionaryBuffer(dictionary);
            for (int id = 0, max = dictionary.getMaxId(); id <= max; id++) {
                buf[id] = parse(dictionary.decodeToBinary(id).toStringUsingUTF8());
            }
        }

        @Override
        public void addValueFromDictionary(int dictionaryId) {
            drive(dict[dictionaryId]);
        }

        @Override
        public void addBinary(Binary value) {
            drive(parse(value.toStringUsingUTF8()));
        }

        private int[] prepareDictionaryBuffer(Dictionary dictionary) {
            int size = dictionary.getMaxId() + 1;
            if (this.dict == null || this.dict.length < size) {
                int capacity = (int) (size * 1.2) + 1;
                this.dict = new int[capacity];
            } else {
                Arrays.fill(this.dict, -1);
            }
            return this.dict;
        }
    }

    abstract static class AbstractLongConverter extends ValueConverter {

        private long[] dict;

        protected AbstractLongConverter() {
            return;
        }

        protected abstract long parse(String value);

        protected abstract void drive(long value);

        @Override
        public boolean hasDictionarySupport() {
            return true;
        }

        @Override
        public void setDictionary(Dictionary dictionary) {
            long[] buf = prepareDictionaryBuffer(dictionary);
            for (int id = 0, max = dictionary.getMaxId(); id <= max; id++) {
                buf[id] = parse(dictionary.decodeToBinary(id).toStringUsingUTF8());
            }
        }

        @Override
        public void addValueFromDictionary(int dictionaryId) {
            drive(dict[dictionaryId]);
        }

        @Override
        public void addBinary(Binary value) {
            drive(parse(value.toStringUsingUTF8()));
        }

        private long[] prepareDictionaryBuffer(Dictionary dictionary) {
            int size = dictionary.getMaxId() + 1;
            if (this.dict == null || this.dict.length < size) {
                int capacity = (int) (size * 1.2) + 1;
                this.dict = new long[capacity];
            } else {
                Arrays.fill(this.dict, -1L);
            }
            return this.dict;
        }
    }

    static final class FromDecimalOption extends AbstractWriter {

        @Override
        protected String toString(Object value) {
            DecimalOption option = (DecimalOption) value;
            return option.get().toPlainString();
        }
    }

    static final class ToDecimalOption extends AbstractConverter<BigDecimal> {

        private DecimalOption target;

        @Override
        public void set(ValueOption<?> value) {
            this.target = (DecimalOption) value;
        }

        @SuppressWarnings("deprecation")
        @Override
        protected void drive(BigDecimal value) {
            target.modify(value);
        }

        @Override
        protected BigDecimal parse(String value) {
            return new BigDecimal(value);
        }
    }

    static final class FromDateOption extends AbstractWriter {

        @Override
        protected String toString(Object value) {
            DateOption option = (DateOption) value;
            return TemporalUtil.toDateString(option.get().getElapsedDays());
        }
    }

    static final class ToDateOption extends AbstractIntConverter {

        private DateOption target;

        @Override
        public void set(ValueOption<?> value) {
            this.target = (DateOption) value;
        }

        @SuppressWarnings("deprecation")
        @Override
        protected void drive(int value) {
            target.modify(value);
        }

        @Override
        protected int parse(String value) {
            int days = TemporalUtil.parseDate(value);
            if (days < 0) {
                throw new IllegalArgumentException(MessageFormat.format(
                        "Invalid date string: {0}",
                        value));
            }
            return days;
        }
    }

    static final class FromDateTimeOption extends AbstractWriter {

        @Override
        protected String toString(Object value) {
            DateTimeOption option = (DateTimeOption) value;
            return TemporalUtil.toTimestampString(option.get().getElapsedSeconds());
        }
    }

    static final class ToDateTimeOption extends AbstractLongConverter {

        private DateTimeOption target;

        @Override
        public void set(ValueOption<?> value) {
            this.target = (DateTimeOption) value;
        }

        @SuppressWarnings("deprecation")
        @Override
        protected void drive(long value) {
            target.modify(value);
        }

        @Override
        protected long parse(String value) {
            long seconds = TemporalUtil.parseTimestamp(value);
            if (seconds < 0) {
                throw new IllegalArgumentException(MessageFormat.format(
                        "Invalid timestamp string: {0}",
                        value));
            }
            return seconds;
        }
    }
}
TOP

Related Classes of com.asakusafw.directio.hive.parquet.AbstractIntConverter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.