io.crate.PartitionName.java Source code

Java tutorial

Introduction

Here is the source code for io.crate.PartitionName.java

Source

/*
 * Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
 * license agreements.  See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.  Crate 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.
 *
 * However, if you have executed another commercial license agreement
 * with Crate these terms will supersede the license and you may use the
 * software solely pursuant to the terms of the relevant commercial agreement.
 */

package io.crate;

import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import io.crate.core.StringUtils;
import io.crate.types.DataTypes;
import io.crate.types.StringType;
import org.apache.commons.codec.binary.Base32;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.io.stream.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class PartitionName implements Streamable {

    private static final Base32 BASE32 = new Base32(true);
    private static final Joiner DOT_JOINER = Joiner.on(".");

    private final List<BytesRef> values;
    private String tableName;

    private String partitionName;
    private String ident;

    private static final Predicate indexNamePartsPredicate = new Predicate<List<String>>() {
        @Override
        public boolean apply(List<String> input) {
            if (input.size() < 4 || !input.get(1).equals(Constants.PARTITIONED_TABLE_PREFIX.substring(1))) {
                return false;
            }
            return true;
        }
    };

    public PartitionName(String tableName, List<BytesRef> values) {
        this.tableName = tableName;
        this.values = values;
    }

    private PartitionName(String tableName) {
        this(tableName, new ArrayList<BytesRef>());
    }

    public boolean isValid() {
        return values.size() > 0;
    }

    @Override
    public void readFrom(StreamInput in) throws IOException {
        tableName = in.readString();
        int size = in.readVInt();
        for (int i = 0; i < size; i++) {
            BytesRef value = DataTypes.STRING.streamer().readValueFrom(in);
            if (value == null) {
                values.add(null);
            } else {
                values.add(value);
            }
        }
    }

    @Override
    public void writeTo(StreamOutput out) throws IOException {
        out.writeString(tableName);
        out.writeVInt(values.size());
        for (BytesRef value : values) {
            StringType.INSTANCE.streamer().writeValueTo(out, value);
        }
    }

    @Nullable
    public void decodeIdent(@Nullable String ident) throws IOException {
        if (ident == null) {
            return;
        }
        byte[] inputBytes = BASE32.decode(ident.toUpperCase(Locale.ROOT));
        BytesStreamInput in = new BytesStreamInput(inputBytes, true);
        int size = in.readVInt();
        for (int i = 0; i < size; i++) {
            BytesRef value = StringType.INSTANCE.streamer().readValueFrom(in);
            if (value == null) {
                values.add(null);
            } else {
                values.add(value);
            }
        }
    }

    @Nullable
    public String encodeIdent() {
        if (values.size() == 0) {
            return null;
        }

        BytesStreamOutput streamOutput = new BytesStreamOutput(estimateSize(values));
        try {
            streamOutput.writeVInt(values.size());
            for (BytesRef value : values) {
                StringType.INSTANCE.streamer().writeValueTo(streamOutput, value);
            }
        } catch (IOException e) {
            //
        }
        String identBase32 = BASE32.encodeAsString(streamOutput.bytes().toBytes()).toLowerCase(Locale.ROOT);
        // decode doesn't need padding, remove it
        int idx = identBase32.indexOf('=');
        if (idx > -1) {
            return identBase32.substring(0, idx);
        }
        return identBase32;
    }

    /**
     * estimates the size the bytesRef values will take if written onto a StreamOutput using the String streamer
     */
    private int estimateSize(List<BytesRef> values) {
        int expectedEncodedSize = 0;
        for (BytesRef value : values) {
            // 5 bytes for the value of the length itself using vInt
            expectedEncodedSize += 5 + (value != null ? value.length : 0);
        }
        return expectedEncodedSize;
    }

    public String stringValue() {
        if (partitionName == null) {
            partitionName = DOT_JOINER.join(Constants.PARTITIONED_TABLE_PREFIX, tableName, ident());
        }
        return partitionName;
    }

    @Nullable
    public String ident() {
        if (ident == null) {
            ident = encodeIdent();
        }
        return ident;
    }

    @Nullable
    public String toString() {
        return stringValue();
    }

    public List<BytesRef> values() {
        return values;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;

        PartitionName that = (PartitionName) o;

        if (!stringValue().equals(that.stringValue()))
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        return stringValue().hashCode();
    }

    public static PartitionName fromString(String partitionTableName, String tableName) {
        assert partitionTableName != null;
        assert tableName != null;

        Tuple<String, String> splitted = split(partitionTableName);
        assert splitted.v1().equals(tableName) : String.format(Locale.ENGLISH, "%s no partition of table %s",
                partitionTableName, tableName);

        return fromPartitionIdent(splitted.v1(), splitted.v2());
    }

    public static PartitionName fromStringSafe(String partitionTableName) {
        assert partitionTableName != null;
        Tuple<String, String> parts = split(partitionTableName);
        return fromPartitionIdent(parts.v1(), parts.v2());
    }

    /**
     * decode a partitionTableName with all of its pre-splitted parts into
     * and instance of <code>PartitionName</code>
     * @param tableName
     * @param partitionIdent
     * @return
     * @throws IOException
     */
    public static PartitionName fromPartitionIdent(String tableName, String partitionIdent) {
        PartitionName partitionName = new PartitionName(tableName);
        partitionName.ident = partitionIdent;
        try {
            partitionName.decodeIdent(partitionIdent);
        } catch (IOException e) {
            throw new IllegalArgumentException(
                    String.format(Locale.ENGLISH, "Invalid partition ident: %s", partitionIdent), e);
        }
        return partitionName;
    }

    public static boolean isPartition(String index, String tableName) {
        List<String> splitted = Splitter.on(".").splitToList(index);
        if (!indexNamePartsPredicate.apply(splitted)) {
            return false;
        }
        return splitted.get(2).equals(tableName);
    }

    public static boolean isPartition(String index) {
        List<String> splitted = Splitter.on(".").splitToList(index);
        return indexNamePartsPredicate.apply(splitted);
    }

    /**
     * split a given partition nameor template name into its parts <code>tableName</code>
     * and <code>valuesString</code>.
     * @param partitionOrTemplateName name of a partition or template
     * @return a {@linkplain org.elasticsearch.common.collect.Tuple}
     *         whose first element is the <code>tableName</code>
     *         and whose second element is the <code>valuesString</code>
     * @throws java.lang.IllegalArgumentException if <code>partitionName</code> is no invalid
     */
    public static Tuple<String, String> split(String partitionOrTemplateName) {
        List<String> splitted = Splitter.on(".").splitToList(partitionOrTemplateName);
        if (!indexNamePartsPredicate.apply(splitted)) {
            throw new IllegalArgumentException("Invalid partition name");
        }
        return new Tuple<>(splitted.get(2), Joiner.on(".").join(splitted.subList(3, splitted.size())));
    }

    /**
     * compute the template name (used with partitioned tables) from a given table name
     */
    public static String templateName(String tableName) {
        return StringUtils.PATH_JOINER.join(Constants.PARTITIONED_TABLE_PREFIX, tableName, "");
    }

    /**
     * extract the tableName from the name of a partition or template
     * @return the tableName as string
     */
    public static String tableName(String partitionOrTemplateName) {
        return PartitionName.split(partitionOrTemplateName).v1();
    }

    /**
     * extract the ident from the name of a partition or template
     * @return the ident as string
     */
    public static String ident(String partitionOrTemplateName) {
        return PartitionName.split(partitionOrTemplateName).v2();
    }
}