/**
   * process any unreferenced collections and then inspect all known collections, scheduling
   * creates/removes/updates
   */
  private void flushCollections(EventSource session) throws HibernateException {

    if (LOG.isTraceEnabled()) {
      LOG.trace("Processing unreferenced collections");
    }

    List list = IdentityMap.entries(session.getPersistenceContext().getCollectionEntries());
    int size = list.size();
    for (int i = 0; i < size; i++) {
      Map.Entry me = (Map.Entry) list.get(i);
      CollectionEntry ce = (CollectionEntry) me.getValue();
      if (!ce.isReached() && !ce.isIgnore()) {
        Collections.processUnreachableCollection((PersistentCollection) me.getKey(), session);
      }
    }

    // Schedule updates to collections:

    if (LOG.isTraceEnabled()) {
      LOG.trace("Scheduling collection removes/(re)creates/updates");
    }

    list = IdentityMap.entries(session.getPersistenceContext().getCollectionEntries());
    size = list.size();
    ActionQueue actionQueue = session.getActionQueue();
    for (int i = 0; i < size; i++) {
      Map.Entry me = (Map.Entry) list.get(i);
      PersistentCollection coll = (PersistentCollection) me.getKey();
      CollectionEntry ce = (CollectionEntry) me.getValue();

      if (ce.isDorecreate()) {
        session.getInterceptor().onCollectionRecreate(coll, ce.getCurrentKey());
        actionQueue.addAction(
            new CollectionRecreateAction(
                coll, ce.getCurrentPersister(), ce.getCurrentKey(), session));
      }
      if (ce.isDoremove()) {
        session.getInterceptor().onCollectionRemove(coll, ce.getLoadedKey());
        actionQueue.addAction(
            new CollectionRemoveAction(
                coll,
                ce.getLoadedPersister(),
                ce.getLoadedKey(),
                ce.isSnapshotEmpty(coll),
                session));
      }
      if (ce.isDoupdate()) {
        session.getInterceptor().onCollectionUpdate(coll, ce.getLoadedKey());
        actionQueue.addAction(
            new CollectionUpdateAction(
                coll,
                ce.getLoadedPersister(),
                ce.getLoadedKey(),
                ce.isSnapshotEmpty(coll),
                session));
      }
    }

    actionQueue.sortCollectionActions();
  }
  /**
   * process any unreferenced collections and then inspect all known collections, scheduling
   * creates/removes/updates
   */
  @SuppressWarnings("unchecked")
  private int flushCollections(
      final EventSource session, final PersistenceContext persistenceContext)
      throws HibernateException {
    LOG.trace("Processing unreferenced collections");

    final Map.Entry<PersistentCollection, CollectionEntry>[] entries =
        IdentityMap.concurrentEntries(
            (Map<PersistentCollection, CollectionEntry>) persistenceContext.getCollectionEntries());

    final int count = entries.length;

    for (Map.Entry<PersistentCollection, CollectionEntry> me : entries) {
      CollectionEntry ce = me.getValue();
      if (!ce.isReached() && !ce.isIgnore()) {
        Collections.processUnreachableCollection(me.getKey(), session);
      }
    }

    // Schedule updates to collections:

    LOG.trace("Scheduling collection removes/(re)creates/updates");

    ActionQueue actionQueue = session.getActionQueue();
    for (Map.Entry<PersistentCollection, CollectionEntry> me :
        IdentityMap.concurrentEntries(
            (Map<PersistentCollection, CollectionEntry>)
                persistenceContext.getCollectionEntries())) {
      PersistentCollection coll = me.getKey();
      CollectionEntry ce = me.getValue();

      if (ce.isDorecreate()) {
        session.getInterceptor().onCollectionRecreate(coll, ce.getCurrentKey());
        actionQueue.addAction(
            new CollectionRecreateAction(
                coll, ce.getCurrentPersister(), ce.getCurrentKey(), session));
      }
      if (ce.isDoremove()) {
        session.getInterceptor().onCollectionRemove(coll, ce.getLoadedKey());
        actionQueue.addAction(
            new CollectionRemoveAction(
                coll,
                ce.getLoadedPersister(),
                ce.getLoadedKey(),
                ce.isSnapshotEmpty(coll),
                session));
      }
      if (ce.isDoupdate()) {
        session.getInterceptor().onCollectionUpdate(coll, ce.getLoadedKey());
        actionQueue.addAction(
            new CollectionUpdateAction(
                coll,
                ce.getLoadedPersister(),
                ce.getLoadedKey(),
                ce.isSnapshotEmpty(coll),
                session));
      }

      // todo : I'm not sure the !wasInitialized part should really be part of this check
      if (!coll.wasInitialized() && coll.hasQueuedOperations()) {
        actionQueue.addAction(
            new QueuedOperationCollectionAction(
                coll, ce.getLoadedPersister(), ce.getLoadedKey(), session));
      }
    }

    actionQueue.sortCollectionActions();

    return count;
  }