docs: private Map<String, Map<String, IndexData>> processIndexes(TableDescription tableDescription,
                                                                 ProjectionExpressionBuilder projectionExpressionBuilder,
                                                                 IndexData baseIndexData) {
          // Collect information about the local secondary indexes.  These will be included with the global indexes below.
          Map<String, IndexData> localIndexes;
          List<LocalSecondaryIndexDescription> localSecondaryIndexes = tableDescription.getLocalSecondaryIndexes();
          if (localSecondaryIndexes != null) {
              localIndexes = new HashMap<>(localSecondaryIndexes.size() + 2);
  
              // We include these as local indexes to make findUsingQueryModel() code below simpler
              localIndexes.put(rangeKeyField, baseIndexData);
              localIndexes.put(null, baseIndexData);
  
              for (LocalSecondaryIndexDescription description : localSecondaryIndexes) {
                  String indexField = getKeyAttributeNames(description.getKeySchema()).getSecond();
                  boolean projectsOverEntity = description.getProjection().getProjectionType().equals("ALL")
                                               || projectionExpressionBuilder != null
                                                  && projectionExpressionBuilder.isCoveredBy(description.getProjection());
  
                  List<String> keyFields = new ArrayList<>(baseIndexData.keyFields);
                  keyFields.add(indexField);
  
                  localIndexes.put(indexField, new IndexData(description.getIndexName(), keyFields, projectsOverEntity));
              }
          } else if (rangeKeyField != null) {
              localIndexes = new HashMap<>(2);
  
              localIndexes.put(rangeKeyField, baseIndexData);
              localIndexes.put(null, baseIndexData);
          } else {
              localIndexes = Collections.singletonMap(null, baseIndexData);
          }
  
          // Process the global secondary indexes.  When done, add the local index information.
          List<GlobalSecondaryIndexDescription> globalSecondaryIndexes = tableDescription.getGlobalSecondaryIndexes();
          if (globalSecondaryIndexes != null) {
              Map<String, Map<String, IndexData>> indexes = new HashMap<>(globalSecondaryIndexes.size() + 1);
  
              for (GlobalSecondaryIndexDescription description : globalSecondaryIndexes) {
                  Pair<String, String> indexFields = getKeyAttributeNames(description.getKeySchema());
                  boolean projectsOverEntity = description.getProjection().getProjectionType().equals("ALL")
                                               || projectionExpressionBuilder != null
                                                  && projectionExpressionBuilder.isCoveredBy(description.getProjection());
  
                  List<String> keyFields = new ArrayList<>();
                  keyFields.add(indexFields.getFirst());
                  if (indexFields.getSecond() != null) {
                      keyFields.add(indexFields.getSecond());
                  }
                  keyFields.add(hashKeyField);
                  if (rangeKeyField != null) {
                      keyFields.add(rangeKeyField);
                  }
  
                  IndexData indexData = new IndexData(description.getIndexName(), keyFields, projectsOverEntity);
  
                  if (!indexes.containsKey(indexFields.getFirst())) {
                      indexes.put(indexFields.getFirst(), new HashMap<String, IndexData>());
                  }
  
                  indexes.get(indexFields.getFirst()).put(indexFields.getSecond(), indexData);
  
                  // In case a query doesn't specify a range key, we still want to select an index for this hash key.
                  // If one has already been selected, pick one that projects over this entity to avoid extra DB reads.
                  IndexData noRangeKeyIndexData = indexes.get(indexFields.getFirst()).get(null);
                  if (noRangeKeyIndexData == null || !noRangeKeyIndexData.projectsOverEntity) {
                      indexes.get(indexFields.getFirst()).put(null, indexData);
                  }
              }
  
              indexes.put(hashKeyField, localIndexes);
  
              return indexes;
          } else {
              return Collections.singletonMap(hashKeyField, localIndexes);
          }
      }