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

io.tarantool.driver.core.metadata.DDLTarantoolSpaceMetadataConverter Maven / Gradle / Ivy

Go to download

Tarantool Cartridge driver for Tarantool versions 1.10+ based on Netty framework

There is a newer version: 0.14.0
Show newest version
package io.tarantool.driver.core.metadata;

import io.tarantool.driver.api.metadata.TarantoolFieldMetadata;
import io.tarantool.driver.api.metadata.TarantoolIndexMetadata;
import io.tarantool.driver.api.metadata.TarantoolIndexPartMetadata;
import io.tarantool.driver.api.metadata.TarantoolIndexType;
import io.tarantool.driver.api.metadata.TarantoolMetadataContainer;
import io.tarantool.driver.exceptions.TarantoolClientException;
import io.tarantool.driver.mappers.converters.ValueConverter;
import org.msgpack.value.ArrayValue;
import org.msgpack.value.StringValue;
import org.msgpack.value.Value;
import org.msgpack.value.ValueFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Populates metadata from results of a call to proxy API function in Tarantool instance. The function result is
 * expected to have the format which is returned by DDL module.
 * See
 * https://github.com/tarantool/ddl#input-data-format
 *
 * @author Sergey Volgin
 * @author Artyom Dubinin
 */
public final class DDLTarantoolSpaceMetadataConverter implements ValueConverter {

    private static final DDLTarantoolSpaceMetadataConverter instance =
        new DDLTarantoolSpaceMetadataConverter();

    private static final long serialVersionUID = -2100651651306707627L;

    private static final int ID_UNKNOWN = -1;

    private static final StringValue SPACES_KEY = ValueFactory.newString("spaces");

    private static final StringValue SPACE_ID_KEY = ValueFactory.newString("id");
    private static final StringValue SPACE_FORMAT_KEY = ValueFactory.newString("format");
    private static final StringValue SPACE_INDEXES_KEY = ValueFactory.newString("indexes");

    private static final StringValue INDEX_NAME_KEY = ValueFactory.newString("name");
    private static final StringValue INDEX_UNIQUE_KEY = ValueFactory.newString("unique");
    private static final StringValue INDEX_TYPE_KEY = ValueFactory.newString("type");
    private static final StringValue INDEX_PARTS_KEY = ValueFactory.newString("parts");

    private static final StringValue INDEX_PARTS_TYPE_KEY = ValueFactory.newString("type");
    private static final StringValue INDEX_PARTS_PATH_KEY = ValueFactory.newString("path");

    private static final ArrayValueToSpaceFormatConverter arrayValueToSpaceFormatConverter
        = ArrayValueToSpaceFormatConverter.getInstance();

    private DDLTarantoolSpaceMetadataConverter() {
    }

    @Override
    public TarantoolMetadataContainer fromValue(Value value) {

        if (!value.isMapValue()) {
            throw new TarantoolClientException("Unsupported space metadata format: expected map");
        }

        Map spacesMap = value.asMapValue().map();

        if (!spacesMap.containsKey(SPACES_KEY) || !spacesMap.get(SPACES_KEY).isMapValue()) {
            throw new TarantoolClientException(
                "Unsupported metadata format: key '" + SPACES_KEY + "' must contain " +
                    "a map of spaces names to space metadata");
        }

        spacesMap = spacesMap.get(SPACES_KEY).asMapValue().map();

        ProxyTarantoolMetadataContainer proxyMetadata = new ProxyTarantoolMetadataContainer();
        for (Value nameValue : spacesMap.keySet()) {
            if (!nameValue.isStringValue()) {
                throw new TarantoolClientException(
                    "Unsupported metadata format: the spaces map keys must be of string type");
            }

            Value spaceValue = spacesMap.get(nameValue);
            if (!spaceValue.isMapValue()) {
                throw new TarantoolClientException(
                    "Unsupported metadata format: the spaces map values must be of map type");
            }
            Map space = spaceValue.asMapValue().map();

            TarantoolSpaceMetadataImpl spaceMetadata = new TarantoolSpaceMetadataImpl();
            spaceMetadata.setOwnerId(ID_UNKNOWN);
            spaceMetadata.setSpaceName(nameValue.asStringValue().asString());

            Value formatValue = space.get(SPACE_FORMAT_KEY);
            if (formatValue == null) {
                throw new TarantoolClientException(
                    "Unsupported space metadata format: key '" + SPACE_FORMAT_KEY + "' not found");
            }
            if (!formatValue.isArrayValue()) {
                throw new TarantoolClientException(
                    "Unsupported space metadata format: key '" + SPACE_FORMAT_KEY + "' value is not a list");
            }

            ArrayValue spaceFormat = formatValue.asArrayValue();
            Map fields = arrayValueToSpaceFormatConverter.fromValue(spaceFormat);
            spaceMetadata.setSpaceFormatMetadata(fields);

            proxyMetadata.addSpace(spaceMetadata);

            Value indexesValue = space.get(SPACE_INDEXES_KEY);
            if (indexesValue != null && indexesValue.isArrayValue() && indexesValue.asArrayValue().size() > 0) {
                List indexes = indexesValue.asArrayValue().list();
                proxyMetadata.addIndexes(spaceMetadata.getSpaceName(), parseIndexes(fields, indexes));
            }
        }
        return proxyMetadata;
    }

    private Map parseIndexes(
        Map fields,
        List indexes) {
        Map indexMetadataMap = new HashMap<>();

        int indexId = 0;
        for (Value indexValueMetadata : indexes) {

            if (!indexValueMetadata.isMapValue()) {
                throw new TarantoolClientException("Unsupported index metadata format: index metadata is not a map");
            }

            Map indexMap = indexValueMetadata.asMapValue().map();

            Value indexNameValue = indexMap.get(INDEX_NAME_KEY);
            if (indexNameValue == null || !indexNameValue.isStringValue()) {
                throw new TarantoolClientException(
                    "Unsupported index metadata format: key '" + INDEX_NAME_KEY + "' must have string value");
            }
            String indexName = indexNameValue.asStringValue().asString();

            Value indexTypeValue = indexMap.get(INDEX_TYPE_KEY);
            if (indexTypeValue == null || !indexTypeValue.isStringValue()) {
                throw new TarantoolClientException(
                    "Unsupported index metadata format: key '" + INDEX_TYPE_KEY + "' must have string value");
            }
            String indexType = indexTypeValue.asStringValue().asString();

            Value indexUniqueValue = indexMap.get(INDEX_UNIQUE_KEY);
            if (indexUniqueValue == null || !indexUniqueValue.isBooleanValue()) {
                throw new TarantoolClientException(
                    "Unsupported index metadata format: key '" + INDEX_UNIQUE_KEY + "' must have boolean value");
            }
            boolean isUnique = indexUniqueValue.asBooleanValue().getBoolean();

            TarantoolIndexOptionsImpl indexOptions = new TarantoolIndexOptionsImpl();
            indexOptions.setUnique(isUnique);

            TarantoolIndexMetadataImpl indexMetadata = new TarantoolIndexMetadataImpl();
            indexMetadata.setSpaceId(ID_UNKNOWN);
            indexMetadata.setIndexId(indexId++);
            indexMetadata.setIndexType(TarantoolIndexType.fromString(indexType));
            indexMetadata.setIndexName(indexName);
            indexMetadata.setIndexOptions(indexOptions);

            Value indexPartsValue = indexMap.get(INDEX_PARTS_KEY);
            if (indexPartsValue == null) {
                throw new TarantoolClientException(
                    "Unsupported index metadata format: key '" + INDEX_PARTS_KEY + "' not found");
            }
            if (!indexPartsValue.isArrayValue()) {
                throw new TarantoolClientException(
                    "Unsupported index metadata format: key '" + INDEX_PARTS_KEY + "' value is not a list");
            }

            List indexParts = indexPartsValue.asArrayValue().list();
            List indexPartMetadata = indexParts.stream()
                .map(parts -> {
                    if (!parts.isMapValue()) {
                        throw new TarantoolClientException(
                            "Unsupported index metadata format: index part metadata is not a map");
                    }

                    Map partsMap = parts.asMapValue().map();

                    Value fieldPathValue = partsMap.get(INDEX_PARTS_PATH_KEY);
                    if (fieldPathValue == null || !fieldPathValue.isStringValue()) {
                        throw new TarantoolClientException("Unsupported index metadata format: key '" +
                            INDEX_PARTS_PATH_KEY + "' must have string value");
                    }
                    String fieldPath = fieldPathValue.asStringValue().asString();
                    int fieldNumber = getFieldNumberFromFieldPath(fields, fieldPath);

                    Value fieldTypeValue = partsMap.get(INDEX_PARTS_TYPE_KEY);
                    if (fieldTypeValue == null || !fieldTypeValue.isStringValue()) {
                        throw new TarantoolClientException("Unsupported index metadata format: key '" +
                            INDEX_PARTS_TYPE_KEY + "' must have string value");
                    }
                    String fieldType = fieldTypeValue.asStringValue().asString();

                    return new TarantoolIndexPartMetadataImpl(fieldNumber, fieldType, fieldPath);
                })
                .collect(Collectors.toList());

            indexMetadata.setIndexParts(indexPartMetadata);

            indexMetadataMap.put(indexName, indexMetadata);
        }

        return indexMetadataMap;
    }

    private int getFieldNumberFromFieldPath(Map fields, String fieldPath) {
        String fieldName = fieldPath;
        int dotPosition = fieldPath.indexOf('.');
        if (dotPosition >= 0) {
            fieldName = fieldPath.substring(0, dotPosition);
        }
        TarantoolFieldMetadata fieldMeta = fields.get(fieldName);
        if (fieldMeta != null) {
            return fieldMeta.getFieldPosition();
        } else {
            try {
                return Integer.parseInt(fieldName);
            } catch (NumberFormatException e) {
                throw new TarantoolClientException("Unsupported index metadata format: " +
                    "unable to determine the field number or name from path %s", fieldPath);
            }
        }
    }

    public static DDLTarantoolSpaceMetadataConverter getInstance() {
        return instance;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy