
software.amazon.awssdk.enhanced.dynamodb.mapper.ImmutableAttribute Maven / Gradle / Ivy
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 software.amazon.awssdk.enhanced.dynamodb.mapper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;
import software.amazon.awssdk.annotations.NotThreadSafe;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.annotations.ThreadSafe;
import software.amazon.awssdk.enhanced.dynamodb.AttributeConverter;
import software.amazon.awssdk.enhanced.dynamodb.AttributeConverterProvider;
import software.amazon.awssdk.enhanced.dynamodb.EnhancedType;
import software.amazon.awssdk.enhanced.dynamodb.internal.mapper.ResolvedImmutableAttribute;
import software.amazon.awssdk.utils.Validate;
/**
* A class that represents an attribute on an mapped immutable item. A {@link StaticImmutableTableSchema} composes
* multiple attributes that map to a common immutable item class.
*
* The recommended way to use this class is by calling
* {@link software.amazon.awssdk.enhanced.dynamodb.TableSchema#builder(Class, Class)}.
* Example:
* {@code
* TableSchema.builder(Customer.class, Customer.Builder.class)
* .addAttribute(String.class,
* a -> a.name("customer_name").getter(Customer::name).setter(Customer.Builder::name))
* // ...
* .build();
* }
*
* It's also possible to construct this class on its own using the static builder. Example:
* {@code
* ImmutableAttribute customerNameAttribute =
* ImmutableAttribute.builder(Customer.class, Customer.Builder.class, String.class)
* .name("customer_name")
* .getter(Customer::name)
* .setter(Customer.Builder::name)
* .build();
* }
* @param the class of the immutable item this attribute maps into.
* @param the class of the builder for the immutable item this attribute maps into.
* @param the class that the value of this attribute converts to.
*/
@SdkPublicApi
@ThreadSafe
public final class ImmutableAttribute {
private final String name;
private final Function getter;
private final BiConsumer setter;
private final Collection tags;
private final EnhancedType type;
private final AttributeConverter attributeConverter;
private ImmutableAttribute(Builder builder) {
this.name = Validate.paramNotNull(builder.name, "name");
this.getter = Validate.paramNotNull(builder.getter, "getter");
this.setter = Validate.paramNotNull(builder.setter, "setter");
this.tags = builder.tags == null ? Collections.emptyList() : Collections.unmodifiableCollection(builder.tags);
this.type = Validate.paramNotNull(builder.type, "type");
this.attributeConverter = builder.attributeConverter;
}
/**
* Constructs a new builder for this class using supplied types.
* @param itemClass The class of the immutable item that this attribute composes.
* @param builderClass The class of the builder for the immutable item that this attribute composes.
* @param attributeType A {@link EnhancedType} that represents the type of the value this attribute stores.
* @return A new typed builder for an attribute.
*/
public static Builder builder(Class itemClass,
Class builderClass,
EnhancedType attributeType) {
return new Builder<>(attributeType);
}
/**
* Constructs a new builder for this class using supplied types.
* @param itemClass The class of the item that this attribute composes.
* @param builderClass The class of the builder for the immutable item that this attribute composes.
* @param attributeClass A class that represents the type of the value this attribute stores.
* @return A new typed builder for an attribute.
*/
public static Builder builder(Class itemClass,
Class builderClass,
Class attributeClass) {
return new Builder<>(EnhancedType.of(attributeClass));
}
/**
* The name of this attribute
*/
public String name() {
return this.name;
}
/**
* A function that can get the value of this attribute from a modelled immutable item it composes.
*/
public Function getter() {
return this.getter;
}
/**
* A function that can set the value of this attribute on a builder for the immutable modelled item it composes.
*/
public BiConsumer setter() {
return this.setter;
}
/**
* A collection of {@link StaticAttributeTag} associated with this attribute.
*/
public Collection tags() {
return this.tags;
}
/**
* A {@link EnhancedType} that represents the type of the value this attribute stores.
*/
public EnhancedType type() {
return this.type;
}
/**
* A custom {@link AttributeConverter} that will be used to convert this attribute.
* If no custom converter was provided, the value will be null.
* @see Builder#attributeConverter
*/
public AttributeConverter attributeConverter() {
return this.attributeConverter;
}
/**
* Converts an instance of this class to a {@link Builder} that can be used to modify and reconstruct it.
*/
public Builder toBuilder() {
return new Builder(this.type).name(this.name)
.getter(this.getter)
.setter(this.setter)
.tags(this.tags)
.attributeConverter(this.attributeConverter);
}
ResolvedImmutableAttribute resolve(AttributeConverterProvider attributeConverterProvider) {
return ResolvedImmutableAttribute.create(this,
converterFrom(attributeConverterProvider));
}
private AttributeConverter converterFrom(AttributeConverterProvider attributeConverterProvider) {
return (attributeConverter != null) ? attributeConverter : attributeConverterProvider.converterFor(type);
}
/**
* A typed builder for {@link ImmutableAttribute}.
* @param the class of the item this attribute maps into.
* @param the class that the value of this attribute converts to.
*/
@NotThreadSafe
public static final class Builder {
private final EnhancedType type;
private String name;
private Function getter;
private BiConsumer setter;
private List tags;
private AttributeConverter attributeConverter;
private Builder(EnhancedType type) {
this.type = type;
}
/**
* The name of this attribute
*/
public Builder name(String name) {
this.name = name;
return this;
}
/**
* A function that can get the value of this attribute from a modelled item it composes.
*/
public Builder getter(Function getter) {
this.getter = getter;
return this;
}
/**
* A function that can set the value of this attribute on a modelled item it composes.
*/
public Builder setter(BiConsumer setter) {
this.setter = setter;
return this;
}
/**
* A collection of {@link StaticAttributeTag} associated with this attribute. Overwrites any existing tags.
*/
public Builder tags(Collection tags) {
this.tags = new ArrayList<>(tags);
return this;
}
/**
* A collection of {@link StaticAttributeTag} associated with this attribute. Overwrites any existing tags.
*/
public Builder tags(StaticAttributeTag... tags) {
this.tags = Arrays.asList(tags);
return this;
}
/**
* Associates a single {@link StaticAttributeTag} with this attribute. Adds to any existing tags.
*/
public Builder addTag(StaticAttributeTag tag) {
if (this.tags == null) {
this.tags = new ArrayList<>();
}
this.tags.add(tag);
return this;
}
/**
* An {@link AttributeConverter} for the attribute type ({@link EnhancedType}), that can convert this attribute.
* It takes precedence over any converter for this type provided by the table schema
* {@link AttributeConverterProvider}.
*/
public Builder attributeConverter(AttributeConverter attributeConverter) {
this.attributeConverter = attributeConverter;
return this;
}
/**
* Builds a {@link StaticAttributeTag} from the values stored in this builder.
*/
public ImmutableAttribute build() {
return new ImmutableAttribute<>(this);
}
}
}