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

software.amazon.smithy.traitcodegen.TraitCodegenSymbolProvider Maven / Gradle / Ivy

/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

package software.amazon.smithy.traitcodegen;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.Instant;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import software.amazon.smithy.codegen.core.Symbol;
import software.amazon.smithy.codegen.core.SymbolProvider;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.node.Node;
import software.amazon.smithy.model.shapes.BigDecimalShape;
import software.amazon.smithy.model.shapes.BigIntegerShape;
import software.amazon.smithy.model.shapes.BlobShape;
import software.amazon.smithy.model.shapes.BooleanShape;
import software.amazon.smithy.model.shapes.ByteShape;
import software.amazon.smithy.model.shapes.DocumentShape;
import software.amazon.smithy.model.shapes.DoubleShape;
import software.amazon.smithy.model.shapes.EnumShape;
import software.amazon.smithy.model.shapes.FloatShape;
import software.amazon.smithy.model.shapes.IntEnumShape;
import software.amazon.smithy.model.shapes.IntegerShape;
import software.amazon.smithy.model.shapes.ListShape;
import software.amazon.smithy.model.shapes.LongShape;
import software.amazon.smithy.model.shapes.MapShape;
import software.amazon.smithy.model.shapes.MemberShape;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.shapes.ShapeVisitor;
import software.amazon.smithy.model.shapes.ShortShape;
import software.amazon.smithy.model.shapes.StringShape;
import software.amazon.smithy.model.shapes.StructureShape;
import software.amazon.smithy.model.shapes.TimestampShape;
import software.amazon.smithy.model.shapes.UnionShape;
import software.amazon.smithy.model.traits.UniqueItemsTrait;
import software.amazon.smithy.utils.CaseUtils;

/**
 * Responsible for mapping Smithy {@link Shape}'s to Java types.
 */
final class TraitCodegenSymbolProvider extends ShapeVisitor.DataShapeVisitor implements SymbolProvider {

    private final String packageNamespace;
    private final String smithyNamespace;
    private final Model model;

    TraitCodegenSymbolProvider(TraitCodegenSettings settings, Model model) {
        this.packageNamespace = settings.packageName();
        this.smithyNamespace = settings.smithyNamespace();
        this.model = model;
    }

    @Override
    public Symbol blobShape(BlobShape shape) {
        throw new UnsupportedOperationException("Blob shapes are not supported at this time.");
    }

    @Override
    public Symbol booleanShape(BooleanShape shape) {
        return TraitCodegenUtils.fromClass(Boolean.class);
    }

    @Override
    public Symbol byteShape(ByteShape shape) {
        return TraitCodegenUtils.fromClass(Byte.class).toBuilder()
                .putProperty(SymbolProperties.UNBOXED_SYMBOL, TraitCodegenUtils.fromClass(byte.class))
                .build();
    }

    @Override
    public Symbol shortShape(ShortShape shape) {
        return TraitCodegenUtils.fromClass(Short.class).toBuilder()
                .putProperty(SymbolProperties.UNBOXED_SYMBOL, TraitCodegenUtils.fromClass(short.class))
                .build();
    }

    @Override
    public Symbol integerShape(IntegerShape shape) {
        return TraitCodegenUtils.fromClass(Integer.class)
                .toBuilder()
                .putProperty(SymbolProperties.UNBOXED_SYMBOL, TraitCodegenUtils.fromClass(int.class))
                .build();
    }

    @Override
    public Symbol intEnumShape(IntEnumShape shape) {
        return getJavaClassSymbol(shape);
    }

    @Override
    public Symbol longShape(LongShape shape) {
        return TraitCodegenUtils.fromClass(Long.class).toBuilder()
                .putProperty(SymbolProperties.UNBOXED_SYMBOL, TraitCodegenUtils.fromClass(long.class))
                .build();
    }

    @Override
    public Symbol floatShape(FloatShape shape) {
        return TraitCodegenUtils.fromClass(Float.class)
                .toBuilder()
                .putProperty(SymbolProperties.UNBOXED_SYMBOL, TraitCodegenUtils.fromClass(float.class))
                .build();
    }

    @Override
    public Symbol doubleShape(DoubleShape shape) {
        return TraitCodegenUtils.fromClass(Double.class)
                .toBuilder()
                .putProperty(SymbolProperties.UNBOXED_SYMBOL, TraitCodegenUtils.fromClass(double.class))
                .build();
    }

    @Override
    public Symbol bigIntegerShape(BigIntegerShape shape) {
        return TraitCodegenUtils.fromClass(BigInteger.class);
    }

    @Override
    public Symbol bigDecimalShape(BigDecimalShape shape) {
        return TraitCodegenUtils.fromClass(BigDecimal.class);
    }

    @Override
    public Symbol listShape(ListShape shape) {
        if (shape.hasTrait(UniqueItemsTrait.class)) {
            return TraitCodegenUtils.fromClass(Set.class).toBuilder()
                    .addReference(toSymbol(shape.getMember()))
                    .putProperty(SymbolProperties.BUILDER_REF_INITIALIZER, "forOrderedSet()")
                    .build();
        }
        return TraitCodegenUtils.fromClass(List.class).toBuilder()
                .addReference(toSymbol(shape.getMember()))
                .putProperty(SymbolProperties.BUILDER_REF_INITIALIZER, "forList()")
                .build();
    }

    @Override
    public Symbol mapShape(MapShape shape) {
        return TraitCodegenUtils.fromClass(Map.class).toBuilder()
                .addReference(shape.getKey().accept(this))
                .addReference(shape.getValue().accept(this))
                .putProperty(SymbolProperties.BUILDER_REF_INITIALIZER, "forOrderedMap()")
                .build();
    }

    @Override
    public Symbol stringShape(StringShape shape) {
        return TraitCodegenUtils.fromClass(String.class);
    }

    @Override
    public Symbol enumShape(EnumShape shape) {
        return getJavaClassSymbol(shape);
    }

    @Override
    public Symbol structureShape(StructureShape shape) {
        return getJavaClassSymbol(shape);
    }

    @Override
    public Symbol documentShape(DocumentShape shape) {
        return TraitCodegenUtils.fromClass(Node.class);
    }

    @Override
    public Symbol memberShape(MemberShape shape) {
        return toSymbol(model.expectShape(shape.getTarget()));
    }

    @Override
    public Symbol timestampShape(TimestampShape shape) {
        return TraitCodegenUtils.fromClass(Instant.class);
    }

    @Override
    public Symbol unionShape(UnionShape shape) {
        throw new UnsupportedOperationException("Union shapes are not supported at this time.");
    }

    @Override
    public Symbol toSymbol(Shape shape) {
        return shape.accept(this);
    }

    @Override
    public String toMemberName(MemberShape member) {
        Shape containerShape = model.expectShape(member.getContainer());
        // If the container is a Map list then we assign a simple "values" holder for the collection
        if (containerShape.isMapShape() || containerShape.isListShape()) {
            return "values";
        // Enum shapes should have upper snake case members
        } else if (containerShape.isEnumShape() || containerShape.isIntEnumShape()) {
            return CaseUtils.toSnakeCase(TraitCodegenUtils.MEMBER_ESCAPER.escape(member.getMemberName()))
                    .toUpperCase(Locale.ROOT);
        }

        if (member.getMemberName().contains("_")) {
            return TraitCodegenUtils.MEMBER_ESCAPER.escape(CaseUtils.toCamelCase(member.getMemberName()));
        } else {
            return TraitCodegenUtils.MEMBER_ESCAPER.escape(member.getMemberName());
        }
    }

    private Symbol getJavaClassSymbol(Shape shape) {
        String name = TraitCodegenUtils.getDefaultName(shape);
        String namespace = TraitCodegenUtils.mapNamespace(smithyNamespace,
                shape.getId().getNamespace(), packageNamespace);
        return Symbol.builder().name(name)
                .namespace(namespace, ".")
                .declarationFile("./" + namespace.replace(".", "/") + "/"  + name + ".java")
                .build();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy