docs: public void performRecovery(ObjectManagerState objectManagerState)
                      throws ObjectManagerException {
          if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
              trace.entry(this,
                          cclass,
                          "performRecovery",
                          objectManagerState);
  
          if (Tracing.isAnyTracingEnabled() && trace.isDebugEnabled())
              trace.debug(this,
                          cclass,
                          "logicalUnitOfWork=" + logicalUnitOfWork + "(LogicalUnitOfWork)"
                                          + "\n transactionState=" + transactionState + "(int)"
                                          + "\n tokensToAdd=" + tokensToAdd + "(java.util.Collection)"
                                          + "\n tokensToReplace=" + tokensToReplace + "(java.util.Collecton)"
                                          + "\n serializedBytesToReplace=" + serializedBytesToReplace + "(java.util.Collection)"
                                          + "\n tokensToOptimisticReplace=" + tokensToOptimisticReplace + "(java.util.Collection)"
                                          + "\n tokensToDelete=" + tokensToDelete + "(java.util.Collection)"
                                          + "\n tokensToNotify=" + tokensToNotify + "(java.util.Collection)");
  
          // In principle we should test to see if objectManagerState.checkpointEndSee is true, 
          // because if it is we dont need to do this processing because the transaction is 
          // already in its correct state, however there is also no harm in processing this again. 
          // We have started an new checkpoint but not completed it.
  
          // Redo the operations of the ManagedObject using its original Transaction.
          Transaction transactionForRecovery = objectManagerState.getTransaction(logicalUnitOfWork);
  
          // Recover the Added ManagedObjects.
          for (java.util.Iterator tokenIterator = tokensToAdd.iterator(); tokenIterator.hasNext();) {
              Token token = (Token) tokenIterator.next();
              ManagedObject existingManagedObject = token.getManagedObject();
              // If a subsequent transaction has deleted the ManagedObject we dont need to recover it.
              if (existingManagedObject != null) {
                  // Revert to constructed state.
                  existingManagedObject.state = ManagedObject.stateConstructed;
                  transactionForRecovery.addFromCheckpoint(existingManagedObject);
              } // if(existingManagedObject != null).
          } // for ... tokensToAdd.
  
          // Recover the Replace ManagedObjects.
          java.util.Iterator serializedBytesIterator = serializedBytesToReplace.iterator();
          for (java.util.Iterator tokenIterator = tokensToReplace.iterator(); tokenIterator.hasNext();) {
              Token token = (Token) tokenIterator.next();
              ManagedObject existingManagedObject = token.getManagedObject();
              byte[] managedObjectBytes = (byte[]) serializedBytesIterator.next();
              ManagedObject replacementManagedObject = ManagedObject.restoreFromSerializedBytes(managedObjectBytes,
                                                                                                objectManagerState);
              // If a subsequent transaction has deleted the ManagedObject we dont need to recover it.
              if (existingManagedObject != null) {
                  // Replace what we already have with this version.
                  transactionForRecovery.lock(existingManagedObject);
                  // Make the underlying object the way it was when we made the original transaction.replace()
                  // call.
                  token.setManagedObject(replacementManagedObject);
                  transactionForRecovery.replaceFromCheckpoint(existingManagedObject,
                                                               managedObjectBytes);
              } // if(existingManagedObject != null).
          } // for ... tokensToReplace.
  
          // Recover the Optimistic Replace ManagedObjects.
          for (java.util.Iterator tokenIterator = tokensToOptimisticReplace.iterator(); tokenIterator.hasNext();) {
              Token token = (Token) tokenIterator.next();
              ManagedObject existingManagedObject = token.getManagedObject();
              // If a subsequent transaction has deleted the ManagedObject we dont need to recover it.
              if (existingManagedObject != null) {
                  transactionForRecovery.optimisticReplaceFromCheckpoint(existingManagedObject);
              } // if(existingManagedObject != null).
          } // for ... tokensToOptimisticReplace.
  
          // Recover the Delete ManagedObjects.
          for (java.util.Iterator tokenIterator = tokensToDelete.iterator(); tokenIterator.hasNext();) {
              Token token = (Token) tokenIterator.next();
              ManagedObject existingManagedObject = token.getManagedObject();
              // If the object has already been deleted we need not do anything.
              if (existingManagedObject != null) {
                  transactionForRecovery.deleteFromCheckpoint(existingManagedObject);
              } // if(existingManagedObject != null).
          } // for ... tokensToDelete.
  
          // Recover the Notify ManagedObjects.
          for (java.util.Iterator tokenIterator = tokensToNotify.iterator(); tokenIterator.hasNext();) {
              Token token = (Token) tokenIterator.next();
              ManagedObject existingManagedObject = token.getManagedObject();
              // If the object has already been deleted we need not do anything.
              if (existingManagedObject != null) {
                  transactionForRecovery.notifyFromCheckpoint(token);
              } // if(existingManagedObject != null).
          } // for ... tokensToNotify.
  
          transactionForRecovery.internalTransaction.resetState(transactionState);
  
          if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
              trace.exit(this,
                         cclass,
                         "performRecovery");
      }