docs: public synchronized void lockAndRegister(RuntimeObject rtObject, int lockMode, boolean cascade, List registeredObjects)
      {
          if(log.isDebugEnabled()) log.debug("Lock and register called for " + rtObject.getIdentity());
          // if current object was already locked, do nothing
          // avoid endless loops when circular object references are used
          if(!registeredObjects.contains(rtObject.getIdentity()))
          {
              if(cascade)
              {
                  // if implicite locking is enabled, first add the current object to
                  // list of registered objects to avoid endless loops on circular objects
                  registeredObjects.add(rtObject.getIdentity());
                  // lock and register 1:1 references first
                  //
                  // If implicit locking is used, we have materialize the main object
                  // to lock the referenced objects too
                  lockAndRegisterReferences(rtObject.getCld(), rtObject.getObjMaterialized(), lockMode, registeredObjects);
              }
              try
              {
                  // perform the lock on the object
                  // we don't need to lock new objects
                  if(!rtObject.isNew())
                  {
                      doSingleLock(rtObject.getCld(), rtObject.getObj(), rtObject.getIdentity(), lockMode);
                  }
                  // after we locked the object, register it to detect status and changes while tx
                  doSingleRegister(rtObject, lockMode);
              }
              catch (Throwable t)
              {
                  //log.error("Locking of obj " + rtObject.getIdentity() + " failed", t);
                  // if registering of object fails release lock on object, because later we don't
                  // get a change to do this.
                  implementation.getLockManager().releaseLock(this, rtObject.getIdentity(), rtObject.getObj());
                  if(t instanceof LockNotGrantedException)
                  {
                      throw (LockNotGrantedException) t;
                  }
                  else
                  {
                      log.error("Unexpected failure while locking", t);
                      throw new LockNotGrantedException("Locking failed for "
                              + rtObject.getIdentity()+ ", nested exception is: [" + t.getClass().getName()
                              + ": " + t.getMessage() + "]");
                  }
              }
              if(cascade)
              {
                  // perform locks and register 1:n and m:n references
                  // If implicit locking is used, we have materialize the main object
                  // to lock the referenced objects too
                  lockAndRegisterCollections(rtObject.getCld(), rtObject.getObjMaterialized(), lockMode, registeredObjects);
              }
          }
      }