/** INTERNAL: Recursive method to set a field value in the given key instance. */
  protected void setFieldValue(
      KeyElementAccessor accessor,
      Object keyInstance,
      DatabaseMapping mapping,
      AbstractSession session,
      int[] elementIndex,
      Object... keyElements) {
    if (mapping.isAggregateMapping()) {
      Object nestedObject = mapping.getRealAttributeValueFromObject(keyInstance, session);

      if (nestedObject == null) {
        nestedObject = getClassInstance(mapping.getReferenceDescriptor().getJavaClass());
        mapping.setRealAttributeValueInObject(keyInstance, nestedObject);
      }

      // keep drilling down the nested mappings ...
      setFieldValue(
          accessor,
          nestedObject,
          mapping
              .getReferenceDescriptor()
              .getObjectBuilder()
              .getMappingForField(accessor.getDatabaseField()),
          session,
          elementIndex,
          keyElements);
    } else {
      Object fieldValue = null;

      if (mapping.isDirectToFieldMapping()) {
        fieldValue = keyElements[elementIndex[0]];
        Converter converter = ((DirectToFieldMapping) mapping).getConverter();
        if (converter != null) {
          fieldValue = converter.convertDataValueToObjectValue(fieldValue, session);
        }
        ++elementIndex[0];
      } else if (mapping.isObjectReferenceMapping()) {
        // what if mapping comes from derived ID. need to get the derived mapping.
        // get reference descriptor and extract pk from target cmp policy
        fieldValue =
            mapping
                .getReferenceDescriptor()
                .getCMPPolicy()
                .createPrimaryKeyInstanceFromPrimaryKeyValues(session, elementIndex, keyElements);
      }

      accessor.setValue(keyInstance, fieldValue);
    }
  }
  /**
   * INTERNAL: Create an instance of the composite primary key class for the key object. Yes the
   * elementIndex looks strange but this is just a simple way to get the index to be
   * pass-by-reference
   */
  public Object createPrimaryKeyInstanceFromPrimaryKeyValues(
      AbstractSession session, int[] elementIndex, Object... keyElements) {
    Object keyInstance = null;
    KeyElementAccessor[] pkElementArray = getKeyClassFields();
    if ((pkElementArray.length == 1) && (pkElementArray[0] instanceof KeyIsElementAccessor)) {
      DatabaseMapping mapping =
          getDescriptor()
              .getObjectBuilder()
              .getMappingForAttributeName(pkElementArray[0].getAttributeName());
      if (mapping.isDirectToFieldMapping()) {
        Converter converter = ((DirectToFieldMapping) mapping).getConverter();
        if (converter != null) {
          return converter.convertDataValueToObjectValue(keyElements[elementIndex[0]], session);
        }
        keyInstance = keyElements[elementIndex[0]];
      } else if (mapping
          .isObjectReferenceMapping()) { // what if mapping comes from derived ID.  need to get the
                                         // derived mapping.
        // get reference descriptor and extract pk from target cmp policy
        keyInstance =
            mapping
                .getReferenceDescriptor()
                .getCMPPolicy()
                .createPrimaryKeyInstanceFromPrimaryKeyValues(session, elementIndex, keyElements);
      }
      ++elementIndex[0]; // remove processed key in case keys are complex and derived
    } else {
      keyInstance = getPKClassInstance();
      // get clone of Key so we can remove values.
      for (int index = 0; index < pkElementArray.length; index++) {
        KeyElementAccessor accessor = pkElementArray[index];
        DatabaseMapping mapping =
            getDescriptor()
                .getObjectBuilder()
                .getMappingForAttributeName(accessor.getAttributeName());
        if (mapping == null) {
          mapping =
              getDescriptor().getObjectBuilder().getMappingForField(accessor.getDatabaseField());
        }

        if (accessor.isNestedAccessor()) {
          // Need to recursively build all the nested objects.
          setFieldValue(
              accessor,
              keyInstance,
              mapping
                  .getReferenceDescriptor()
                  .getObjectBuilder()
                  .getMappingForField(accessor.getDatabaseField()),
              session,
              elementIndex,
              keyElements);
        } else {
          // Not nested but may be a single layer aggregate so check.
          if (mapping.isAggregateMapping()) {
            mapping =
                mapping
                    .getReferenceDescriptor()
                    .getObjectBuilder()
                    .getMappingForField(accessor.getDatabaseField());
          }

          setFieldValue(accessor, keyInstance, mapping, session, elementIndex, keyElements);
        }
      }
    }

    return keyInstance;
  }