Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2011-2015 Amazon Technologies, 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://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 java.util.Map;
 import java.util.Set;
 
A class responsible for parsing the primary key and index schema of a table POJO.
 
 
     private final Map<Class<?>, TableIndexesInfotableIndexesInfoCache =
             new HashMap<Class<?>, TableIndexesInfo>();

    
Parse the given POJO class and return the CreateTableRequest for the DynamoDB table it represents. Note that the returned request does not include the required ProvisionedThroughput parameters for the primary table and the GSIs, and that all secondary indexes are initialized with the default projection type - KEY_ONLY.

Parameters:
clazz The POJO class.
config The DynamoDBMapperConfig which contains the TableNameOverrides parameter used to determine the table name.
reflector The DynamoDBReflector that provides all the relevant getters of the POJO.
 
             Class<?> clazz,
             DynamoDBMapperConfig config,
             DynamoDBReflector reflector,
             ItemConverter converter) {
 
         CreateTableRequest createTableRequest = new CreateTableRequest();
         createTableRequest.setTableName(DynamoDBMapper.internalGetTableName(clazznullconfig));
 
         // Primary keys
         Method pHashKeyGetter = reflector.getPrimaryHashKeyGetter(clazz);
         AttributeDefinition pHashAttrDefinition = getKeyAttributeDefinition(pHashKeyGetterconverter);
         createTableRequest.withKeySchema(new KeySchemaElement(pHashAttrDefinition.getAttributeName(), .));
         // Primary range
         Method pRangeKeyGetter = reflector.getPrimaryRangeKeyGetter(clazz);
         AttributeDefinition pRangeAttrDefinition = null;
         if (pRangeKeyGetter != null) {
             pRangeAttrDefinition = getKeyAttributeDefinition(pRangeKeyGetterconverter);
             createTableRequest.withKeySchema(new KeySchemaElement(pRangeAttrDefinition.getAttributeName(), .));
         }
 
         // Parse the index schema
         TableIndexesInfo indexesInfo = parseTableIndexes(clazzreflector);
         if ( indexesInfo.getGlobalSecondaryIndexes().isEmpty() == false ) {
             createTableRequest.setGlobalSecondaryIndexes(indexesInfo.getGlobalSecondaryIndexes());
         }
         if ( indexesInfo.getLocalSecondaryIndexes().isEmpty() == false ) {
             createTableRequest.setLocalSecondaryIndexes(indexesInfo.getLocalSecondaryIndexes());
         }
 
         // Aggregate all key attribute definitions
         Map<StringAttributeDefinitionattrDefinitions = new HashMap<StringAttributeDefinition>();
         // Hash key definition
         putAfterCheckConflict(attrDefinitionspHashAttrDefinition);
         // Range key definition
         if (pRangeKeyGetter != null) {
             putAfterCheckConflict(attrDefinitionspRangeAttrDefinition);
         }
         for (Method indexKeyGetter : indexesInfo.getIndexKeyGetters()) {
            AttributeDefinition indexKeyAttrDefinition = getKeyAttributeDefinition(indexKeyGetterconverter);
            putAfterCheckConflict(attrDefinitionsindexKeyAttrDefinition);
        }
        createTableRequest.setAttributeDefinitions(attrDefinitions.values());
        return createTableRequest;
    }
    TableIndexesInfo parseTableIndexes(final Class<?> clazzfinal DynamoDBReflector reflector) {
        synchronized() {
            if ( !.containsKey(clazz) ) {
                TableIndexesInfo tableIndexInfo = new TableIndexesInfo();
                String pHashName = reflector.getPrimaryHashKeyName(clazz);
                for (Method getter : reflector.getRelevantGetters(clazz)) {
                    // Only consider 0-arg getters
                    if (getter.getParameterTypes().length != 0) {
                        continue;
                    }
                    String attributeName = reflector.getAttributeName(getter);
                    if (ReflectionUtils.getterOrFieldHasAnnotation(getterDynamoDBIndexHashKey.class)) {
                        DynamoDBIndexHashKey indexHashKeyAnnotation = ReflectionUtils
                                .getAnnotationFromGetterOrField(getterDynamoDBIndexHashKey.class);
                        String gsiName = indexHashKeyAnnotation.globalSecondaryIndexName();
                        String[] gsiNames = indexHashKeyAnnotation.globalSecondaryIndexNames();
                        boolean singleGsiName = gsiName != null &&
                                                gsiName.length() != 0;
                        boolean multipleGsiNames = gsiNames != null &&
                                                   gsiNames.length != 0;
                        if ( singleGsiName && multipleGsiNames) {
                            throw new DynamoDBMappingException(
                                    "@DynamoDBIndexHashKey annotation on getter " + getter +
                                    " contains both globalSecondaryIndexName and globalSecondaryIndexNames.");
                        } else if ( (!singleGsiName) && (!multipleGsiNames) ) {
                            throw new DynamoDBMappingException(
                                    "@DynamoDBIndexHashKey annotation on getter " + getter +
                                    " doesn't contain any index name.");
                        }
                        if (singleGsiName) {
                            tableIndexInfo.addGsiKeys(gsiNameattributeNamenull);
                        } else if (multipleGsiNames) {
                            for (String gsi : gsiNames) {
                                tableIndexInfo.addGsiKeys(gsiattributeNamenull);
                            }
                        }
                        tableIndexInfo.addIndexKeyGetter(getter);
                    }
                    if (ReflectionUtils.getterOrFieldHasAnnotation(getterDynamoDBIndexRangeKey.class)) {
                        DynamoDBIndexRangeKey indexRangeKeyAnnotation = ReflectionUtils
                                .getAnnotationFromGetterOrField(getterDynamoDBIndexRangeKey.class);
                        String gsiName = indexRangeKeyAnnotation.globalSecondaryIndexName();
                        String[] gsiNames = indexRangeKeyAnnotation.globalSecondaryIndexNames();
                        String lsiName = indexRangeKeyAnnotation.localSecondaryIndexName();
                        String[] lsiNames = indexRangeKeyAnnotation.localSecondaryIndexNames();
                        boolean singleGsiName = gsiName != null &&
                                                gsiName.length() != 0;
                        boolean multipleGsiNames = gsiNames != null &&
                                                   gsiNames.length != 0;
                        boolean singleLsiName = lsiName != null &&
                                                lsiName.length() != 0;
                        boolean multipleLsiNames = lsiNames != null &&
                                                   lsiNames.length != 0;
                        if ( singleGsiName && multipleGsiNames ) {
                            throw new DynamoDBMappingException(
                                    "@DynamoDBIndexRangeKey annotation on getter " + getter +
                                    " contains both globalSecondaryIndexName and globalSecondaryIndexNames.");
                        }
                        if ( singleLsiName && multipleLsiNames ) {
                            throw new DynamoDBMappingException(
                                    "@DynamoDBIndexRangeKey annotation on getter " + getter +
                                    " contains both localSecondaryIndexName and localSecondaryIndexNames.");
                        }
                        if ( (!singleGsiName) && (!multipleGsiNames) && (!singleLsiName) && (!multipleLsiNames) ) {
                            throw new DynamoDBMappingException(
                                    "@DynamoDBIndexRangeKey annotation on getter " + getter +
                                    " doesn't contain any index name.");
                        }
                        if (singleGsiName) {
                            tableIndexInfo.addGsiKeys(gsiNamenullattributeName);
                        } else if (multipleGsiNames) {
                            for (String gsi : gsiNames) {
                                tableIndexInfo.addGsiKeys(gsinullattributeName);
                            }
                        }
                        if (singleLsiName) {
                            tableIndexInfo.addLsiRangeKey(lsiNamepHashNameattributeName);
                        } else if (multipleLsiNames) {
                            for (String lsi : lsiNames) {
                                tableIndexInfo.addLsiRangeKey(lsipHashNameattributeName);
                            }
                        }
                        tableIndexInfo.addIndexKeyGetter(getter);
                    }
                } // end of for loop
                .put(clazztableIndexInfo);
            } // end of the if-cache-does-not-contain block
            return .get(clazz);
        } // end of synchronized block
    }
            Method keyGetter,
            ItemConverter converter) {
        DynamoDBMapperFieldModel fieldModel = converter.getFieldModel(keyGetter);
        String keyAttrName = fieldModel.getDynamoDBAttributeName();
        DynamoDBAttributeType keyType = fieldModel.getDynamoDBAttributeType();
        if (keyType == . ||
            keyType == . ||
            keyType == .) {
            return new AttributeDefinition(keyAttrNamekeyType.toString());
        }
        throw new DynamoDBMappingException(
                "The key attribute must be in a scalar type "
                + "(String, Number or Binary).");
    }
    private static void putAfterCheckConflict(Map<StringAttributeDefinitionmap,
                                              AttributeDefinition attrDefinition) {
        String attrName = attrDefinition.getAttributeName();
        AttributeDefinition existingDefinition = map.get(attrName);
        if (existingDefinition != null && !existingDefinition.equals(attrDefinition)) {
            throw new DynamoDBMappingException(
                    "Found conflicting definitions for attribute [" + attrName + "]: " +
                    existingDefinition + " and " + attrDefinition + ".");
        } else {
            map.put(attrNameattrDefinition);
        }
    }

    
This class contains all the information about a table's index schema parsed from a table POJO class.
    static class TableIndexesInfo {

        
Used for mapping an index key name to all the applicable indexes.
        private final Map<StringSet<String>> lsiRangeKeyNameToIndexNames =
                new HashMap<StringSet<String>>();
        private final Map<StringSet<String>> gsiHashKeyNameToIndexNames =
                new HashMap<StringSet<String>>();
        private final Map<StringSet<String>> gsiRangeKeyNameToIndexNames =
                new HashMap<StringSet<String>>();

        
Note that the KeySchema in each LocalSecondaryIndex does not include the hash key.
        private final Map<StringLocalSecondaryIndexlsiNameToLsiDefinition = new HashMap<StringLocalSecondaryIndex>();
        private final Map<StringGlobalSecondaryIndexgsiNameToGsiDefinition = new HashMap<StringGlobalSecondaryIndex>();

        
All getter methods of index key attributes.
        private final Set<MethodindexKeyGetters = new HashSet<Method>();

        
Returns the names of all the annotated local secondary indexes that use the given attribute as the index range key.
        public Set<StringgetLsiNamesByIndexRangeKey(String indexRangeKeyName) {
            Set<StringlsiNames = .get(indexRangeKeyName);
            if (lsiNames != null) {
                lsiNames = Collections.unmodifiableSet(lsiNames);
            }
            return lsiNames;
        }

        
Returns the names of all the annotated global secondary indexes that use the given attribute as the index hash key.
        public Set<StringgetGsiNamesByIndexHashKey(String indexHashKeyName) {
            Set<StringgsiNames = .get(indexHashKeyName);
            if (gsiNames != null) {
                gsiNames = Collections.unmodifiableSet(gsiNames);
            }
            return gsiNames;
        }

        
Returns the names of all the annotated global secondary indexes that use the given attribute as the index range key.
        public Set<StringgetGsiNamesByIndexRangeKey(String indexRangeKeyName) {
            Set<StringgsiNames = .get(indexRangeKeyName);
            if (gsiNames != null) {
                gsiNames = Collections.unmodifiableSet(gsiNames);
            }
            return gsiNames;
        }

        
Returns the names of all the annotated local secondary indexes of this POJO class.
        public Set<StringgetAllLsiNames() {
            return Collections.unmodifiableSet(.keySet());
        }

        
Returns the names of all the annotated global secondary indexes of this POJO class.
        public Set<StringgetAllGsiNames() {
            return Collections.unmodifiableSet(.keySet());
        }
        /*
         * Private interfaces
         */
        private void addGsiKeys(String gsiNameString gsiHashKeyNameString gsiRangeKeyName) {
            GlobalSecondaryIndex gsi;
            if (.containsKey(gsiName)) {
                GlobalSecondaryIndex existingGsi = .get(gsiName);
                gsi = existingGsi;
                if ( !gsiName.equals(existingGsi.getIndexName()) ) {
                    throw new IllegalStateException("Found invalid state of an existing GlobalSecondaryIndex object " +
                            "associated with the GSI [" + gsiName + "].");
                }
                for (KeySchemaElement existingKey : existingGsi.getKeySchema()) {
                    String existingKeyName = existingKey.getAttributeName();
                    String existingKeyType = existingKey.getKeyType();
                    if (..toString().equals(existingKeyType)) {
                        if (gsiHashKeyName != null && !gsiHashKeyName.equals(existingKeyName)) {
                            throw new DynamoDBMappingException("Multiple hash keys [" + existingKeyName + ", " + gsiHashKeyName +
                                    "] are found for the GSI [" + gsiName + "]. " +
                                    "Each index allows at most one range key attribute.");
                        }
                    } else if (..toString().equals(existingKeyType)) {
                        if (gsiRangeKeyName != null && !gsiRangeKeyName.equals(existingKeyName)) {
                            throw new DynamoDBMappingException("Multiple range keys [" + existingKeyName + ", " + gsiRangeKeyName +
                                    "] are found for the GSI [" + gsiName + "]. " +
                                    "Each index allows at most one range key attribute.");
                        }
                    } else {
                        // Existing key element is neither HASH nor RANGE.
                        throw new IllegalStateException("Found invalid state of an existing GlobalSecondaryIndex object " +
                                "associated with the GSI [" + gsiName + "].");
                    }
                }
            } else {
                gsi = new GlobalSecondaryIndex()
                    .withIndexName(gsiName)
                    .withProjection(new Projection().withProjectionType(.));
                .put(gsiNamegsi);
            }
            if (gsiHashKeyName != null) {
                // Make sure that the HASH key element is always inserted at the beginning of the list
                if (gsi.getKeySchema() == null || gsi.getKeySchema().isEmpty()) {
                    gsi.withKeySchema(new KeySchemaElement(gsiHashKeyName.));
                } else {
                    LinkedList<KeySchemaElementorderedKeys = new LinkedList<KeySchemaElement>(gsi.getKeySchema());
                    orderedKeys.addFirst(new KeySchemaElement(gsiHashKeyName.));
                    gsi.setKeySchema(orderedKeys);
                }
                // Register the mapping from the hash key name to the GSI name
                mapGsiHashKeyToIndexName(gsiHashKeyNamegsiName);
            }
            if (gsiRangeKeyName != null) {
                gsi.withKeySchema(new KeySchemaElement(gsiRangeKeyName.));
                // Register the mapping from the range key name to the GSI name
                mapGsiRangeKeyToIndexName(gsiRangeKeyNamegsiName);
            }
        }
        private void addLsiRangeKey(String lsiNameString pHashKeyNameString lsiRangeKeyName) {
            if (pHashKeyName == null) {
                throw new IllegalArgumentException("The name of the primary hash key must be specified.");
            }
            if (.containsKey(lsiName)) {
                LocalSecondaryIndex existingLsi = .get(lsiName);
                if ( !lsiName.equals(existingLsi.getIndexName())
                        || existingLsi.getKeySchema() == null
                        || existingLsi.getKeySchema().size() != 2  // the hash key element should be already added
                        || !..toString().equals(existingLsi.getKeySchema().get(1).getKeyType()) ) {
                    throw new IllegalStateException("Found invalid state of an existing LocalSecondaryIndex object " +
                            "associated with the LSI [" + lsiName + "].");
                }
                String existingLsiRangeKeyName = existingLsi.getKeySchema().get(1).getAttributeName();
                if ( !existingLsiRangeKeyName.equals(lsiRangeKeyName) ) {
                    throw new DynamoDBMappingException("Multiple range keys [" + existingLsiRangeKeyName + ", " + lsiRangeKeyName +
                            "] are found for the LSI [" + lsiName + "]. " +
                            "Each index allows at most one range key attribute.");
                }
            } else {
                .put(
                        lsiName,
                        new LocalSecondaryIndex()
                                .withIndexName(lsiName)
                                .withKeySchema(
                                        new KeySchemaElement(pHashKeyName.),
                                        new KeySchemaElement(lsiRangeKeyName.))
                                .withProjection(new Projection().withProjectionType(.)));
                mapLsiRangeKeyToIndexName(lsiRangeKeyNamelsiName);
            }
        }
        private void mapLsiRangeKeyToIndexName(String lsiRangeKeyNameString lsiName) {
            mapIndexKeyToIndexName(lsiRangeKeyNamelsiName);
        }
        private void mapGsiHashKeyToIndexName(String gsiHashKeyNameString gsiName) {
            mapIndexKeyToIndexName(gsiHashKeyNamegsiName);
        }
        private void mapGsiRangeKeyToIndexName(String gsiRangeKeyNameString gsiName) {
            mapIndexKeyToIndexName(gsiRangeKeyNamegsiName);
        }
        private void mapIndexKeyToIndexName(Map<StringSet<String>> indexKeyNameToIndexNames,
                                            String indexKeyName,
                                            String indexName) {
            if (indexKeyNameToIndexNames.get(indexKeyName) == null) {
                Set<StringindexNames = new HashSet<String>();
                indexNames.add(indexName);
                indexKeyNameToIndexNames.put(indexKeyNameindexNames);
            } else {
                indexKeyNameToIndexNames.get(indexKeyName).add(indexName);
            }
        }
        private void addIndexKeyGetter(Method indexKeyGetter) {
            .add(indexKeyGetter);
        }
        private Set<MethodgetIndexKeyGetters() {
            return Collections.unmodifiableSet();
        }
            return Collections.unmodifiableCollection(.values());
        }
            return Collections.unmodifiableCollection(.values());
        }
    }
New to GrepCode? Check out our FAQ X