/**
   * Commit all of the objects as a single transaction. This should commit the object in the correct
   * order to maintain referential integrity.
   */
  public void commitAllObjectsWithChangeSet(UnitOfWorkChangeSet uowChangeSet)
      throws RuntimeException, DatabaseException, OptimisticLockException {
    reinitialize();
    this.isActive = true;
    this.session.beginTransaction();
    try {
      // PERF: if the number of classes in the project is large this loop can be a perf issue.
      // If only one class types changed, then avoid loop.
      if ((uowChangeSet.getObjectChanges().size() + uowChangeSet.getNewObjectChangeSets().size())
          <= 1) {
        Iterator<Class> classes = uowChangeSet.getNewObjectChangeSets().keySet().iterator();
        if (classes.hasNext()) {
          Class theClass = classes.next();
          commitNewObjectsForClassWithChangeSet(uowChangeSet, theClass);
        }
        classes = uowChangeSet.getObjectChanges().keySet().iterator();
        if (classes.hasNext()) {
          Class theClass = classes.next();
          commitChangedObjectsForClassWithChangeSet(uowChangeSet, theClass);
        }
      } else {
        // The commit order is all of the classes ordered by dependencies, this is done for deadlock
        // avoidance.
        List commitOrder = getCommitOrder();
        int size = commitOrder.size();
        for (int index = 0; index < size; index++) {
          Class theClass = (Class) commitOrder.get(index);
          commitAllObjectsForClassWithChangeSet(uowChangeSet, theClass);
        }
      }

      if (hasDeferredCalls()) {
        // Perform all batched up calls, done to avoid dependencies.
        for (List<Object[]> calls : this.deferredCalls.values()) {
          for (Object[] argument : calls) {
            ((DatabaseQueryMechanism) argument[1])
                .executeDeferredCall((DatasourceCall) argument[0]);
          }
        }
      }

      if (hasDataModifications()) {
        // Perform all batched up data modifications, done to avoid dependencies.
        for (Map.Entry<DatabaseMapping, List<Object[]>> entry : this.dataModifications.entrySet()) {
          List<Object[]> events = entry.getValue();
          int size = events.size();
          DatabaseMapping mapping = entry.getKey();
          for (int index = 0; index < size; index++) {
            Object[] event = events.get(index);
            mapping.performDataModificationEvent(event, getSession());
          }
        }
      }

      if (hasObjectsToDelete()) {
        // These are orphaned objects, to be deleted from private ownership updates.
        // TODO: These should be added to the unit of work deleted so they are deleted in the
        // correct order.
        List objects = getObjectsToDelete();
        int size = objects.size();
        reinitialize();
        for (int index = 0; index < size; index++) {
          this.session.deleteObject(objects.get(index));
        }
      }

      this.session.commitTransaction();
    } catch (RuntimeException exception) {
      this.session.rollbackTransaction();
      throw exception;
    } finally {
      reinitialize();
      this.isActive = false;
    }
  }