1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  *  http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 
16 package software.amazon.awssdk.enhanced.dynamodb;
17 
18 import java.util.Collection;
19 import java.util.Map;
20 import java.util.Optional;
21 import software.amazon.awssdk.annotations.SdkPublicApi;
22 import software.amazon.awssdk.annotations.ThreadSafe;
23 import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
24 
25 /**
26  * Interface for an object the stores structural information about a DynamoDb table.
27  */
28 @SdkPublicApi
29 @ThreadSafe
30 public interface TableMetadata {
31     /**
32      * Returns the attribute name of the partition key for an index.
33      *
34      * @param indexName The name of the index.
35      * @return The attribute name representing the partition key for this index.
36      * @throws IllegalArgumentException if the index does not exist in the metadata or does not have a partition key
37      * associated with it..
38      */
indexPartitionKey(String indexName)39     String indexPartitionKey(String indexName);
40 
41     /**
42      * Returns the attribute name of the sort key for an index.
43      *
44      * @param indexName The name of the index.
45      * @return Optional of the attribute name representing the sort key for this index; empty if the index does not
46      * have a sort key.
47      */
indexSortKey(String indexName)48     Optional<String> indexSortKey(String indexName);
49 
50     /**
51      * Returns a custom metadata object. These objects are used by extensions to the library, therefore the type of
52      * object stored is flexible and does not need to be known by the interface.
53      *
54      * @param key A unique key for the metadata object. This namespace is shared by all extensions, so it is
55      *            recommended best practice to qualify it with the name of your extension.
56      * @param objectClass The java class that the object will be cast to before returning. An exception will be
57      *                    thrown if the stored object cannot be cast to this class.
58      * @param <T> The flexible type for the object being returned. The compiler will typically infer this.
59      * @return An optional containing custom metadata object or empty if the object was not found.
60      */
customMetadataObject(String key, Class<? extends T> objectClass)61     <T> Optional<T> customMetadataObject(String key, Class<? extends T> objectClass);
62 
63     /**
64      * Returns all the names of attributes associated with the keys of a specified index.
65      *
66      * @param indexName The name of the index.
67      * @return A collection of all key attribute names for that index.
68      */
indexKeys(String indexName)69     Collection<String> indexKeys(String indexName);
70 
71     /**
72      * Returns all the names of attributes associated with any index (primary or secondary) known for this table.
73      * Additionally any additional attributes that are deemed to be 'key-like' in how they should be treated will
74      * also be returned. An example of a 'key-like' attribute that is not actually a key is one tagged as a 'version'
75      * attribute when using the versioned record extension.
76      *
77      * @return A collection of all key attribute names for the table.
78      *
79      * @deprecated Use {@link #keyAttributes()} instead.
80      */
81     @Deprecated
allKeys()82     Collection<String> allKeys();
83 
84     /**
85      * Returns metadata about all the known indices for this table.
86      * @return A collection of {@link IndexMetadata} containing information about the indices.
87      */
indices()88     Collection<IndexMetadata> indices();
89 
90     /**
91      * Returns all custom metadata for this table. These entries are used by extensions to the library, therefore the
92      * value type of each metadata object stored in the map is not known and is provided as {@link Object}.
93      * <p>
94      * This method should not be used to inspect individual custom metadata objects, instead use
95      * {@link TableMetadata#customMetadataObject(String, Class)} ()} as that will perform a type-safety check on the
96      * retrieved object.
97      * @return A map of all the custom metadata for this table.
98      */
customMetadata()99     Map<String, Object> customMetadata();
100 
101     /**
102      * Returns metadata about all the known 'key' attributes for this table, such as primary and secondary index keys,
103      * or any other attribute that forms part of the structure of the table.
104      * @return A collection of {@link KeyAttributeMetadata} containing information about the keys.
105      */
keyAttributes()106     Collection<KeyAttributeMetadata> keyAttributes();
107 
108     /**
109      * Returns the DynamoDb scalar attribute type associated with a key attribute if one is applicable.
110      * @param keyAttribute The key attribute name to return the scalar attribute type of.
111      * @return Optional {@link ScalarAttributeType} of the attribute, or empty if attribute is a non-scalar type.
112      * @throws IllegalArgumentException if the keyAttribute is not found.
113      */
scalarAttributeType(String keyAttribute)114     Optional<ScalarAttributeType> scalarAttributeType(String keyAttribute);
115 
116     /**
117      * Returns the attribute name used as the primary partition key for the table.
118      *
119      * @return The primary partition key attribute name.
120      * @throws IllegalArgumentException if the primary partition key is not known.
121      */
primaryPartitionKey()122     default String primaryPartitionKey() {
123         return indexPartitionKey(primaryIndexName());
124     }
125 
126     /**
127      * Returns the attribute name used as the primary sort key for the table.
128      *
129      * @return An optional of the primary sort key attribute name; empty if this key is not known.
130      */
primarySortKey()131     default Optional<String> primarySortKey() {
132         return indexSortKey(primaryIndexName());
133     }
134 
135     /**
136      * Returns the names of the attributes that make up the primary key for the table.
137      *
138      * @return A collection of attribute names that make up the primary key for the table.
139      */
primaryKeys()140     default Collection<String> primaryKeys() {
141         return indexKeys(primaryIndexName());
142     }
143 
144     /**
145      * Returns an arbitrary constant that should be used as the primary index name. This pattern creates a
146      * common abstraction and simplifies the implementation of operations that also work on secondary indices such as
147      * scan() and query().
148      *
149      * @return An arbitrary constant that internally represents the primary index name.
150      */
primaryIndexName()151     static String primaryIndexName() {
152         // Must include illegal symbols that cannot be used by a real index.
153         // This value is arbitrary and ephemeral but could end up being serialized with TableMetadata through the
154         // actions of a client, so it should not be altered unless absolutely necessary.
155         return "$PRIMARY_INDEX";
156     }
157 }
158