@Override
  protected AbstractRecord buildCompositeRow(
      Object attributeValue,
      AbstractSession session,
      AbstractRecord parentRow,
      WriteType writeType) {
    ClassDescriptor classDesc = null;
    try {
      classDesc = getReferenceDescriptor(attributeValue, session);
    } catch (Exception e) {
      // do nothing
    }
    XMLField xmlFld = (XMLField) getField();
    if (xmlFld.hasLastXPathFragment() && xmlFld.getLastXPathFragment().hasLeafElementType()) {
      XMLRecord xmlRec = (XMLRecord) parentRow;
      xmlRec.setLeafElementType(xmlFld.getLastXPathFragment().getLeafElementType());
    }
    XMLRecord parent = (XMLRecord) parentRow;

    if (classDesc != null) {
      return buildCompositeRowForDescriptor(classDesc, attributeValue, session, parent, writeType);
    } else {
      if (attributeValue instanceof Element
          && getKeepAsElementPolicy() == UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT) {
        return new DOMRecord((Element) attributeValue);
      } else {
        Node newNode =
            XPathEngine.getInstance()
                .create((XMLField) getField(), parent.getDOM(), attributeValue, session);
        DOMRecord newRow = new DOMRecord(newNode);
        return newRow;
      }
    }
  }
  /** INTERNAL: */
  @Override
  public void writeFromObjectIntoRow(
      Object object, AbstractRecord row, AbstractSession session, WriteType writeType)
      throws DescriptorException {
    if (this.isReadOnly()) {
      return;
    }

    Object attributeValue = this.getAttributeValueFromObject(object);
    if (attributeValue == null) {
      row.put(this.getField(), null);
      return;
    }

    ContainerPolicy cp = this.getContainerPolicy();

    Vector nestedRows = new Vector(cp.sizeFor(attributeValue));
    Object iter = cp.iteratorFor(attributeValue);
    if (null != iter) {
      while (cp.hasNext(iter)) {
        Object element = cp.next(iter, session);
        // convert the value - if necessary
        element =
            convertObjectValueToDataValue(element, session, ((XMLRecord) row).getMarshaller());
        if (element == null) {
          XMLNullRepresentationType nullRepresentation =
              getNullPolicy().getMarshalNullRepresentation();
          if (nullRepresentation == XMLNullRepresentationType.XSI_NIL) {
            nestedRows.add(XMLRecord.NIL);
          } else if (nullRepresentation == XMLNullRepresentationType.EMPTY_NODE) {
            Node emptyNode =
                XPathEngine.getInstance()
                    .createUnownedElement(((XMLRecord) row).getDOM(), (XMLField) field);
            DOMRecord nestedRow = new DOMRecord(emptyNode);
            nestedRows.add(nestedRow);
          }
        } else {
          nestedRows.addElement(buildCompositeRow(element, session, row, writeType));
        }
      }
    }

    Object fieldValue = null;
    if (!nestedRows.isEmpty()) {
      fieldValue =
          this.getDescriptor()
              .buildFieldValueFromNestedRows(nestedRows, getStructureName(), session);
    }
    row.put(this.getField(), fieldValue);
  }
 /**
  * INTERNAL: When using the DOM Platform, this method is responsible for marshalling null values
  * for the XML Composite Object Mapping.
  *
  * @param record
  * @param object
  * @param field
  * @return true if this method caused any objects to be marshaled, else false.
  */
 public boolean compositeObjectMarshal(
     AbstractMarshalRecord record, Object object, Field field, CoreAbstractSession session) {
   if (marshalNullRepresentation == XMLNullRepresentationType.XSI_NIL) {
     record.put(field, XMLRecord.NIL);
     return true;
   } else {
     // EMPTY_NODE - Write out empty element - Required
     if (marshalNullRepresentation == XMLNullRepresentationType.EMPTY_NODE) {
       Node element = XPathEngine.getInstance().createUnownedElement(record.getDOM(), field);
       record.put(field, element);
       return true;
     } else {
       // ABSENT_NODE - Write out nothing - Optional
       return false;
     }
   }
 }
  /**
   * Build and return a database row that contains a foreign key for the specified reference object.
   * This will be stored in the nested row(s).
   */
  protected XMLRecord extractKeyRowFromReferenceObject(
      Object object, AbstractSession session, XMLRecord parentRecord) {
    Element newNode =
        XPathEngine.getInstance()
            .createUnownedElement(parentRecord.getDOM(), getForeignKeyGroupingElement());
    XMLRecord result = new DOMRecord(newNode);
    result.setSession(session);

    for (int i = 0; i < this.getSourceForeignKeyFields().size(); i++) {
      DatabaseField fkField = (DatabaseField) getSourceForeignKeyFields().get(i);
      if (object == null) {
        result.add(fkField, null);
      } else {
        DatabaseField pkField =
            (DatabaseField) this.getSourceForeignKeysToTargetKeys().get(fkField);
        Object value =
            this.getReferenceDescriptor()
                .getObjectBuilder()
                .extractValueFromObjectForField(object, pkField, session);
        result.add(fkField, value);
      }
    }
    return result;
  }