private void applyProjectionForIndexInit(List currrentRuntimeIters)
        throws FunctionDomainException, TypeMismatchException, NameResolutionException,
        QueryInvocationTargetException, IMQException {

      if (QueryMonitor.isLowMemory()) {
        throw new IMQException(
            "Index creation canceled due to low memory");
      }

      NonTXEntry temp;

      // Evaluate NonTXEntry for index on entries or additional projections
      // on Entry or just entry value.
      if (isFirstItrOnEntry && additionalProj != null) {
        temp = (NonTXEntry) additionalProj.evaluate(initContext);
      } else {
        temp = (NonTXEntry) ((RuntimeIterator) currrentRuntimeIters.get(0))
            .evaluate(initContext);
      }

      RegionEntry re = temp.getRegionEntry();
      Object indxResultSet;

      if (iteratorSize == 1) {
        indxResultSet = isFirstItrOnEntry
            ? additionalProj == null ? temp
                : ((RuntimeIterator) currrentRuntimeIters.get(0)).evaluate(initContext)
            : additionalProj.evaluate(initContext);
      } else {
        Object[] tuple = new Object[iteratorSize];
        int i = isFirstItrOnEntry ? 0 : 1;
        for (; i < iteratorSize; i++) {
          RuntimeIterator iter = (RuntimeIterator) currrentRuntimeIters.get(i);
          tuple[i] = iter.evaluate(initContext);
        }
        if (!isFirstItrOnEntry) {
          tuple[0] = additionalProj.evaluate(initContext);
        }
        Support.Assert(indexResultSetType instanceof StructTypeImpl,
            "The Index ResultType should have been an instance of StructTypeImpl rather than ObjectTypeImpl. The indxeResultType is "
                + indexResultSetType);
        indxResultSet = new StructImpl((StructTypeImpl) indexResultSetType, tuple);
      }

      // Key must be evaluated after indexResultSet evaluation is done as Entry might be getting
      // destroyed and so if value is UNDEFINED, key will definitely will be UNDEFINED.
      Object indexKey = isFirstItrOnEntry ? indexedExpr.evaluate(initContext)
          : modifiedIndexExpr.evaluate(initContext);
      // based on the first key convert the rest to PdxString or String
      if (!isIndexedPdxKeysFlagSet) {
        setPdxStringFlag(indexKey);
      }
      indexKey = getPdxStringForIndexedPdxKeys(indexKey);
      addMapping(indexKey, indxResultSet, re);
    }
This function is used to obtain Index data at the time of index creation. Each element of the
List is an Object Array of size 3. The 0th element of Object Array stores the value of Index
Expression. The 1st element of ObjectArray contains the RegionEntry object ( If the boolean
isFirstItrOnEntry is false, then the 0th iterator will give us the Region.Entry object which
can be used to obtain the underlying RegionEntry object. If the boolean is true & additional
projection attribute is not null, then the Region.Entry object can be obtained by evaluating
the additional projection attribute. If the boolean isFirstItrOnEntry is true & additional
projection attribute is null, then the 0th iterator itself will evaluate to Region.Entry
Object.
<p>
The 2nd element of Object Array contains the Struct object ( tuple) created. If the boolean
isFirstItrOnEntry is false, then the first attribute of the Struct object is obtained by
evaluating the additional projection attribute.
geode-core/src/main/java/org/apache/geode/cache/query/internal/index/AbstractIndex.java