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

io.trino.hive.formats.line.openxjson.OpenXJsonOptions Maven / Gradle / Ivy

There is a newer version: 465
Show newest version
/*
 * 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 io.trino.hive.formats.line.openxjson;

import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class OpenXJsonOptions
{
    public static final OpenXJsonOptions DEFAULT_OPEN_X_JSON_OPTIONS = builder().build();

    static final Set HIVE_SERDE_CLASS_NAMES = ImmutableSet.of("org.openx.data.jsonserde.JsonSerDe");

    private static final String CASE_INSENSITIVE_KEY = "case.insensitive";
    private static final String FIELD_MAPPING_KEY_PREFIX = "mapping.";
    private static final String IGNORE_MALFORMED_JSON_KEY = "ignore.malformed.json";
    private static final String DOTS_IN_FIELD_NAMES_KEY = "dots.in.keys";
    private static final String EXPLICIT_NULL_KEY = "explicit.null";
    private static final String TIMESTAMP_FORMATS_KEY = "timestamp.formats";

    private final boolean ignoreMalformedJson;
    private final Map fieldNameMappings;
    private final boolean caseInsensitive;
    private final boolean dotsInFieldNames;
    private final boolean explicitNull;
    private final List timestampFormats;

    private OpenXJsonOptions(
            boolean ignoreMalformedJson,
            Map fieldNameMappings,
            boolean caseInsensitive,
            boolean dotsInFieldNames,
            boolean explicitNull,
            List timestampFormats)
    {
        this.ignoreMalformedJson = ignoreMalformedJson;
        this.fieldNameMappings = ImmutableMap.copyOf(fieldNameMappings);
        this.caseInsensitive = caseInsensitive;
        this.dotsInFieldNames = dotsInFieldNames;
        this.explicitNull = explicitNull;
        this.timestampFormats = ImmutableList.copyOf(timestampFormats);
    }

    public boolean isIgnoreMalformedJson()
    {
        return ignoreMalformedJson;
    }

    public Map getFieldNameMappings()
    {
        return fieldNameMappings;
    }

    public boolean isCaseInsensitive()
    {
        return caseInsensitive;
    }

    public boolean isDotsInFieldNames()
    {
        return dotsInFieldNames;
    }

    public boolean isExplicitNull()
    {
        return explicitNull;
    }

    public List getTimestampFormats()
    {
        return timestampFormats;
    }

    public Map toSchema()
    {
        ImmutableMap.Builder schema = ImmutableMap.builder();

        if (ignoreMalformedJson) {
            schema.put(IGNORE_MALFORMED_JSON_KEY, "true");
        }

        if (!caseInsensitive) {
            schema.put(CASE_INSENSITIVE_KEY, "false");
        }

        for (Entry entry : fieldNameMappings.entrySet()) {
            schema.put(FIELD_MAPPING_KEY_PREFIX + entry.getKey(), entry.getValue());
        }

        if (dotsInFieldNames) {
            schema.put(DOTS_IN_FIELD_NAMES_KEY, "true");
        }

        if (explicitNull) {
            schema.put(EXPLICIT_NULL_KEY, "true");
        }

        if (!timestampFormats.isEmpty()) {
            schema.put(TIMESTAMP_FORMATS_KEY, String.join(",", timestampFormats));
        }
        return schema.buildOrThrow();
    }

    public static OpenXJsonOptions fromSchema(Map serdeProperties)
    {
        Builder builder = builder();

        if ("true".equalsIgnoreCase(serdeProperties.get(IGNORE_MALFORMED_JSON_KEY))) {
            builder.ignoreMalformedJson();
        }

        boolean caseInsensitive = "true".equalsIgnoreCase(serdeProperties.getOrDefault(CASE_INSENSITIVE_KEY, "true"));
        if (!caseInsensitive) {
            builder.caseSensitive();
        }

        for (Entry entry : serdeProperties.entrySet()) {
            String key = entry.getKey();
            if (key.startsWith(FIELD_MAPPING_KEY_PREFIX)) {
                String hiveField = key.substring(FIELD_MAPPING_KEY_PREFIX.length());
                String jsonField = caseInsensitive ? entry.getValue().toLowerCase(Locale.ROOT) : entry.getValue();
                builder.addFieldMapping(hiveField, jsonField);
            }
        }

        if ("true".equalsIgnoreCase(serdeProperties.get(DOTS_IN_FIELD_NAMES_KEY))) {
            builder.dotsInFieldNames();
        }

        if ("true".equalsIgnoreCase(serdeProperties.get(EXPLICIT_NULL_KEY))) {
            builder.explicitNull();
        }

        String timestampFormats = serdeProperties.get(TIMESTAMP_FORMATS_KEY);
        if (timestampFormats != null) {
            // Note there is no escaping for commas in timestamps
            builder.timestampFormats(Splitter.on(',').splitToList(timestampFormats));
        }

        return builder.build();
    }

    public static Builder builder()
    {
        return new Builder();
    }

    public static Builder builder(OpenXJsonOptions options)
    {
        return new Builder(options);
    }

    public static class Builder
    {
        private boolean ignoreMalformedJson;
        private boolean caseInsensitive = true;
        private final ImmutableMap.Builder fieldNameMappings = ImmutableMap.builder();
        private boolean dotsInFieldNames;
        private boolean explicitNull;
        private List timestampFormats = ImmutableList.of();

        public Builder() {}

        private Builder(OpenXJsonOptions options)
        {
            ignoreMalformedJson = options.isIgnoreMalformedJson();
            caseInsensitive = options.isCaseInsensitive();
            fieldNameMappings.putAll(options.getFieldNameMappings());
            dotsInFieldNames = options.isDotsInFieldNames();
            explicitNull = options.isExplicitNull();
            timestampFormats = options.getTimestampFormats();
        }

        public Builder ignoreMalformedJson()
        {
            this.ignoreMalformedJson = true;
            return this;
        }

        public Builder addFieldMapping(String hiveField, String jsonField)
        {
            this.fieldNameMappings.put(hiveField, jsonField);
            return this;
        }

        public Builder caseSensitive()
        {
            this.caseInsensitive = false;
            return this;
        }

        public Builder dotsInFieldNames()
        {
            this.dotsInFieldNames = true;
            return this;
        }

        public Builder explicitNull()
        {
            this.explicitNull = true;
            return this;
        }

        public Builder timestampFormats(String... timestampFormats)
        {
            return timestampFormats(ImmutableList.copyOf(timestampFormats));
        }

        public Builder timestampFormats(List timestampFormats)
        {
            this.timestampFormats = timestampFormats;
            return this;
        }

        public OpenXJsonOptions build()
        {
            return new OpenXJsonOptions(
                    ignoreMalformedJson,
                    fieldNameMappings.buildOrThrow(),
                    caseInsensitive,
                    dotsInFieldNames,
                    explicitNull,
                    timestampFormats);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy