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

com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperFieldModel Maven / Gradle / Ivy

/*
 * Copyright 2011-2022 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.
 * You may obtain a copy of the License at:
 *
 *    http://aws.amazon.com/apache2.0
 *
 * 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 com.amazonaws.services.dynamodbv2.datamodeling;

import static com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAutoGenerateStrategy.ALWAYS;
import static com.amazonaws.services.dynamodbv2.datamodeling.StandardTypeConverters.Vector.LIST;
import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.BEGINS_WITH;
import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.BETWEEN;
import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.CONTAINS;
import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.EQ;
import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.GE;
import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.GT;
import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.IN;
import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.NULL;
import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.LE;
import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.LT;
import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.NE;
import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.NOT_CONTAINS;
import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.NOT_NULL;

import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.ComparisonOperator;
import com.amazonaws.services.dynamodbv2.model.Condition;
import com.amazonaws.services.dynamodbv2.model.KeyType;

import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Field model.
 *
 * @param  The object type.
 * @param  The field model type.
 */
public class DynamoDBMapperFieldModel implements DynamoDBAutoGenerator, DynamoDBTypeConverter {

    public static enum DynamoDBAttributeType { B, N, S, BS, NS, SS, BOOL, NULL, L, M; };

    private final DynamoDBMapperFieldModel.Properties properties;
    private final DynamoDBTypeConverter converter;
    private final DynamoDBAttributeType attributeType;
    private final DynamoDBMapperFieldModel.Reflect reflect;

    /**
     * Creates a new field model instance.
     * @param builder The builder.
     */
    private DynamoDBMapperFieldModel(final DynamoDBMapperFieldModel.Builder builder) {
        this.properties = builder.properties;
        this.converter = builder.converter;
        this.attributeType = builder.attributeType;
        this.reflect = builder.reflect;
    }

    /**
     * @deprecated replaced by {@link DynamoDBMapperFieldModel#name}
     */
    @Deprecated
    public String getDynamoDBAttributeName() {
        return properties.attributeName();
    }

    /**
     * @deprecated replaced by {@link DynamoDBMapperFieldModel#attributeType}
     */
    @Deprecated
    public DynamoDBAttributeType getDynamoDBAttributeType() {
        return attributeType;
    }

    /**
     * Gets the attribute name.
     * @return The attribute name.
     */
    public final String name() {
        return properties.attributeName();
    }

    /**
     * Gets the value from the object instance.
     * @param object The object instance.
     * @return The value.
     */
    public final V get(final T object) {
        return reflect.get(object);
    }

    /**
     * Sets the value on the object instance.
     * @param object The object instance.
     * @param value The value.
     */
    public final void set(final T object, final V value) {
        reflect.set(object, value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final DynamoDBAutoGenerateStrategy getGenerateStrategy() {
        if (properties.autoGenerator() != null) {
            return properties.autoGenerator().getGenerateStrategy();
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final V generate(final V currentValue) {
        return properties.autoGenerator().generate(currentValue);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final AttributeValue convert(final V object) {
        return converter.convert(object);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final V unconvert(final AttributeValue object) {
        return converter.unconvert(object);
    }

    /**
     * Get the current value from the object and convert it.
     * @param object The object instance.
     * @return The converted value.
     */
    public final AttributeValue getAndConvert(final T object) {
        return convert(get(object));
    }

    /**
     * Unconverts the value and sets it on the object.
     * @param object The object instance.
     * @param value The attribute value.
     */
    public final void unconvertAndSet(final T object, final AttributeValue value) {
        set(object, unconvert(value));
    }

    /**
     * Gets the DynamoDB attribute type.
     * @return The DynamoDB attribute type.
     */
    public final DynamoDBAttributeType attributeType() {
        return attributeType;
    }

    /**
     * Gets the key type.
     * @return The key type if a key field, null otherwise.
     */
    public final KeyType keyType() {
        return properties.keyType();
    }

    /**
     * Indicates if this attribute is a version attribute.
     * @return True if it is, false otherwise.
     */
    public final boolean versioned() {
        return properties.versioned();
    }

    /**
     * Gets the global secondary indexes.
     * @param keyType The key type.
     * @return The list of global secondary indexes.
     */
    public final List globalSecondaryIndexNames(final KeyType keyType) {
        if (properties.globalSecondaryIndexNames().containsKey(keyType)) {
            return properties.globalSecondaryIndexNames().get(keyType);
        }
        return Collections.emptyList();
    }

    /**
     * Gets the local secondary indexes.
     * @return The list of local secondary indexes.
     */
    public final List localSecondaryIndexNames() {
        return properties.localSecondaryIndexNames();
    }

    /**
     * Returns true if the field has any indexes.
     * @return True if the propery matches.
     */
    public final boolean indexed() {
        return !properties.globalSecondaryIndexNames().isEmpty() || !properties.localSecondaryIndexNames().isEmpty();
    }

    /**
     * Creates a condition which filters on the specified value.
     * @param value The value.
     * @return The condition.
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#BEGINS_WITH
     * @see com.amazonaws.services.dynamodbv2.model.Condition
     */
    public final Condition beginsWith(final V value) {
        return new Condition().withComparisonOperator(BEGINS_WITH).withAttributeValueList(convert(value));
    }

    /**
     * Creates a condition which filters on the specified values.
     * @param lo The start of the range (inclusive).
     * @param hi The end of the range (inclusive).
     * @return The condition.
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#BETWEEN
     * @see com.amazonaws.services.dynamodbv2.model.Condition
     */
    public final Condition between(final V lo, final V hi) {
        return new Condition().withComparisonOperator(BETWEEN).withAttributeValueList(convert(lo), convert(hi));
    }

    /**
     * Creates a condition which filters on the specified value.
     * @param value The value.
     * @return The condition.
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#CONTAINS
     * @see com.amazonaws.services.dynamodbv2.model.Condition
     */
    public final Condition contains(final V value) {
        return new Condition().withComparisonOperator(CONTAINS).withAttributeValueList(convert(value));
    }

    /**
     * Creates a condition which filters on the specified value.
     * @param value The value.
     * @return The condition.
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#EQ
     * @see com.amazonaws.services.dynamodbv2.model.Condition
     */
    public final Condition eq(final V value) {
        return new Condition().withComparisonOperator(EQ).withAttributeValueList(convert(value));
    }

    /**
     * Creates a condition which filters on the specified value.
     * @param value The value.
     * @return The condition.
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#GE
     * @see com.amazonaws.services.dynamodbv2.model.Condition
     */
    public final Condition ge(final V value) {
        return new Condition().withComparisonOperator(GE).withAttributeValueList(convert(value));
    }

    /**
     * Creates a condition which filters on the specified value.
     * @param value The value.
     * @return The condition.
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#GT
     * @see com.amazonaws.services.dynamodbv2.model.Condition
     */
    public final Condition gt(final V value) {
        return new Condition().withComparisonOperator(GT).withAttributeValueList(convert(value));
    }

    /**
     * Creates a condition which filters on the specified values.
     * @param values The values.
     * @return The condition.
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#IN
     * @see com.amazonaws.services.dynamodbv2.model.Condition
     */
    public final Condition in(final Collection values) {
        return new Condition().withComparisonOperator(IN).withAttributeValueList(LIST.convert(values, this));
    }

    /**
     * Creates a condition which filters on the specified values.
     * @param values The values.
     * @return The condition.
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#IN
     * @see com.amazonaws.services.dynamodbv2.model.Condition
     */
    public final Condition in(final V ... values) {
        return in(Arrays.asList(values));
    }

    /**
     * Creates a condition which filters on the specified value.
     * @return The condition.
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#NULL
     * @see com.amazonaws.services.dynamodbv2.model.Condition
     */
    public final Condition isNull() {
        return new Condition().withComparisonOperator(NULL);
    }

    /**
     * Creates a condition which filters on the specified value.
     * @param value The value.
     * @return The condition.
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#LE
     * @see com.amazonaws.services.dynamodbv2.model.Condition
     */
    public final Condition le(final V value) {
        return new Condition().withComparisonOperator(LE).withAttributeValueList(convert(value));
    }

    /**
     * Creates a condition which filters on the specified value.
     * @param value The value.
     * @return The condition.
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#LT
     * @see com.amazonaws.services.dynamodbv2.model.Condition
     */
    public final Condition lt(final V value) {
        return new Condition().withComparisonOperator(LT).withAttributeValueList(convert(value));
    }

    /**
     * Creates a condition which filters on the specified value.
     * @param value The value.
     * @return The condition.
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#NE
     * @see com.amazonaws.services.dynamodbv2.model.Condition
     */
    public final Condition ne(final V value) {
        return new Condition().withComparisonOperator(NE).withAttributeValueList(convert(value));
    }

    /**
     * Creates a condition which filters on the specified value.
     * @param value The value.
     * @return The condition.
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#NOT_CONTAINS
     * @see com.amazonaws.services.dynamodbv2.model.Condition
     */
    public final Condition notContains(final V value) {
        return new Condition().withComparisonOperator(NOT_CONTAINS).withAttributeValueList(convert(value));
    }

    /**
     * Creates a condition which filters on the specified value.
     * @return The condition.
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#NOT_NULL
     * @see com.amazonaws.services.dynamodbv2.model.Condition
     */
    public final Condition notNull() {
        return new Condition().withComparisonOperator(NOT_NULL);
    }

    /**
     * Creates a condition which filters on any non-null argument; if {@code lo}
     * is null a {@code LE} condition is applied on {@code hi}, if {@code hi}
     * is null a {@code GE} condition is applied on {@code lo}.
     * @param lo The start of the range (inclusive).
     * @param hi The end of the range (inclusive).
     * @return The condition or null if both arguments are null.
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#BETWEEN
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#EQ
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#GE
     * @see com.amazonaws.services.dynamodbv2.model.ComparisonOperator#LE
     * @see com.amazonaws.services.dynamodbv2.model.Condition
     */
    public final Condition betweenAny(final V lo, final V hi) {
        return lo == null ? (hi == null ? null : le(hi)) : (hi == null ? ge(lo) : (lo.equals(hi) ? eq(lo) : between(lo,hi)));
    }

    /**
     * {@link DynamoDBMapperFieldModel} builder.
     */
    static class Builder {
        private final DynamoDBMapperFieldModel.Properties properties;
        private DynamoDBTypeConverter converter;
        private DynamoDBMapperFieldModel.Reflect reflect;
        private DynamoDBAttributeType attributeType;
        private Class targetType;

        public Builder(Class targetType, DynamoDBMapperFieldModel.Properties properties) {
            this.properties = properties;
            this.targetType = targetType;
        }

        public final Builder with(DynamoDBTypeConverter converter) {
            this.converter = converter;
            return this;
        }

        public final Builder with(DynamoDBAttributeType attributeType) {
            this.attributeType = attributeType;
            return this;
        }

        public final Builder with(DynamoDBMapperFieldModel.Reflect reflect) {
            this.reflect = reflect;
            return this;
        }

        public final DynamoDBMapperFieldModel build() {
            final DynamoDBMapperFieldModel result = new DynamoDBMapperFieldModel(this);
            if ((result.keyType() != null || result.indexed()) && !result.attributeType().name().matches("[BNS]")) {
                throw new DynamoDBMappingException(String.format(
                    "%s[%s]; only scalar (B, N, or S) type allowed for key",
                    targetType.getSimpleName(), result.name()
                ));
            } else if (result.keyType() != null && result.getGenerateStrategy() == ALWAYS) {
                throw new DynamoDBMappingException(String.format(
                    "%s[%s]; auto-generated key and ALWAYS not allowed",
                    targetType.getSimpleName(), result.name()
                ));
            }
            return result;
        }
    }

    /**
     * The field model properties.
     */
    static interface Properties {
        public String attributeName();
        public KeyType keyType();
        public boolean versioned();
        public Map> globalSecondaryIndexNames();
        public List localSecondaryIndexNames();
        public DynamoDBAutoGenerator autoGenerator();

        static final class Immutable implements Properties {
            private final String attributeName;
            private final KeyType keyType;
            private final boolean versioned;
            private final Map> globalSecondaryIndexNames;
            private final List localSecondaryIndexNames;
            private final DynamoDBAutoGenerator autoGenerator;

            public Immutable(final Properties properties) {
                this.attributeName = properties.attributeName();
                this.keyType = properties.keyType();
                this.versioned = properties.versioned();
                this.globalSecondaryIndexNames = properties.globalSecondaryIndexNames();
                this.localSecondaryIndexNames = properties.localSecondaryIndexNames();
                this.autoGenerator = properties.autoGenerator();
            }

            @Override
            public final String attributeName() {
                return this.attributeName;
            }

            @Override
            public final KeyType keyType() {
                return this.keyType;
            }

            @Override
            public final boolean versioned() {
                return this.versioned;
            }

            @Override
            public final Map> globalSecondaryIndexNames() {
                return this.globalSecondaryIndexNames;
            }

            @Override
            public final List localSecondaryIndexNames() {
                return this.localSecondaryIndexNames;
            }

            @Override
            public final DynamoDBAutoGenerator autoGenerator() {
                return this.autoGenerator;
            }
        }
    }

    /**
     * Get/set reflection operations.
     * @param  The object type.
     * @param  The value type.
     */
    static interface Reflect {
        public V get(T object);
        public void set(T object, V value);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy