io.airlift.drift.codec.metadata.ThriftFieldMetadata.java Source code

Java tutorial

Introduction

Here is the source code for io.airlift.drift.codec.metadata.ThriftFieldMetadata.java

Source

/*
 * Copyright (C) 2012 Facebook, Inc.
 *
 * 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.airlift.drift.codec.metadata;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;

import javax.annotation.concurrent.Immutable;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument;
import static io.airlift.drift.annotations.ThriftField.Requiredness;
import static io.airlift.drift.annotations.ThriftIdlAnnotation.RECURSIVE_REFERENCE_ANNOTATION_KEY;
import static java.util.Objects.requireNonNull;

/**
 * ThriftFieldMetadata defines a single thrift field including the value extraction and injection
 * points.
 */
@Immutable
public class ThriftFieldMetadata {
    private final short id;
    private final ThriftTypeReference thriftTypeReference;
    private final String name;
    private final FieldKind fieldKind;
    private final List<ThriftInjection> injections;
    private final Map<String, String> idlAnnotations;
    private final Optional<ThriftConstructorInjection> constructorInjection;
    private final Optional<ThriftMethodInjection> methodInjection;
    private final Optional<ThriftExtraction> extraction;
    private final Optional<TypeCoercion> coercion;
    private final ImmutableList<String> documentation;
    private final boolean isRecursiveReference;
    private final Requiredness requiredness;

    public ThriftFieldMetadata(short id, boolean isLegacyId, boolean isRecursiveReference,
            Requiredness requiredness, Map<String, String> idlAnnotations, ThriftTypeReference thriftTypeReference,
            String name, FieldKind fieldKind, List<ThriftInjection> injections,
            Optional<ThriftConstructorInjection> constructorInjection,
            Optional<ThriftMethodInjection> methodInjection, Optional<ThriftExtraction> extraction,
            Optional<TypeCoercion> coercion) {
        this.isRecursiveReference = isRecursiveReference;
        this.requiredness = requiredness;
        this.thriftTypeReference = requireNonNull(thriftTypeReference, "thriftType is null");
        this.fieldKind = requireNonNull(fieldKind, "type is null");
        this.name = requireNonNull(name, "name is null");
        this.injections = ImmutableList.copyOf(requireNonNull(injections, "injections is null"));
        this.constructorInjection = requireNonNull(constructorInjection, "constructorInjection is null");
        this.methodInjection = requireNonNull(methodInjection, "methodInjection is null");

        this.extraction = requireNonNull(extraction, "extraction is null");
        this.coercion = requireNonNull(coercion, "coercion is null");

        switch (fieldKind) {
        case THRIFT_FIELD:
            if (isLegacyId) {
                checkArgument(id < 0, "isLegacyId should only be specified on fields with negative IDs");
            } else {
                checkArgument(id >= 0, "isLegacyId must be specified on fields with negative IDs");
            }
            break;
        case THRIFT_UNION_ID:
            checkArgument(isLegacyId, "isLegacyId should be implicitly set on ThriftUnionId fields");
            checkArgument(id == Short.MIN_VALUE, "thrift union id must be Short.MIN_VALUE");
            break;
        }

        checkArgument(
                !injections.isEmpty() || extraction.isPresent() || constructorInjection.isPresent()
                        || methodInjection.isPresent(),
                "A thrift field must have an injection or extraction point");

        this.id = id;

        if (extraction.isPresent()) {
            if (extraction.get() instanceof ThriftFieldExtractor) {
                ThriftFieldExtractor e = (ThriftFieldExtractor) extraction.get();
                this.documentation = ThriftCatalog.getThriftDocumentation(e.getField());
            } else if (extraction.get() instanceof ThriftMethodExtractor) {
                ThriftMethodExtractor e = (ThriftMethodExtractor) extraction.get();
                this.documentation = ThriftCatalog.getThriftDocumentation(e.getMethod());
            } else {
                this.documentation = ImmutableList.of();
            }
        } else {
            // no extraction = no documentation
            this.documentation = ImmutableList.of();
        }

        this.idlAnnotations = idlAnnotations;
    }

    public short getId() {
        return id;
    }

    public ThriftType getThriftType() {
        return thriftTypeReference.get();
    }

    public Requiredness getRequiredness() {
        return requiredness;
    }

    public String getName() {
        return name;
    }

    public FieldKind getType() {
        return fieldKind;
    }

    public Map<String, String> getIdlAnnotations() {
        ImmutableMap.Builder<String, String> annotationsBuilder = ImmutableMap.builder();
        annotationsBuilder.putAll(idlAnnotations);

        if (isRecursiveReference()) {
            annotationsBuilder.put(RECURSIVE_REFERENCE_ANNOTATION_KEY, "true");
        }

        return annotationsBuilder.build();
    }

    public boolean isTypeReferenceRecursive() {
        return thriftTypeReference.isRecursive();
    }

    public boolean isRecursiveReference() {
        return isRecursiveReference;
    }

    public boolean isInternal() {
        switch (getType()) {
        // These are normal thrift fields (i.e. they should be emitted by the drift2thrift generator)
        case THRIFT_FIELD:
            return false;

        // Other fields types are used internally in drift, but do not make up part of the external
        // thrift interface
        default:
            return true;
        }
    }

    public boolean isReadOnly() {
        return injections.isEmpty() && !constructorInjection.isPresent() && !methodInjection.isPresent();
    }

    public boolean isWriteOnly() {
        return !extraction.isPresent();
    }

    public List<ThriftInjection> getInjections() {
        return injections;
    }

    public Optional<ThriftConstructorInjection> getConstructorInjection() {
        return constructorInjection;
    }

    public Optional<ThriftMethodInjection> getMethodInjection() {
        return methodInjection;
    }

    public Optional<ThriftExtraction> getExtraction() {
        return extraction;
    }

    public Optional<TypeCoercion> getCoercion() {
        return coercion;
    }

    public ImmutableList<String> getDocumentation() {
        return documentation;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        ThriftFieldMetadata that = (ThriftFieldMetadata) o;
        return id == that.id && Objects.equals(thriftTypeReference, that.thriftTypeReference)
                && Objects.equals(name, that.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, thriftTypeReference, name);
    }

    @Override
    public String toString() {
        return toStringHelper(this).add("id", id).add("thriftTypeReference", thriftTypeReference).add("name", name)
                .add("fieldKind", fieldKind).add("injections", injections)
                .add("constructorInjection", constructorInjection).add("methodInjection", methodInjection)
                .add("extraction", extraction).add("coercion", coercion).toString();
    }
}