docs: private void lockReachableObjects(Identity oid, Object userObject,
              Object cacheObject, int lock, Stack stack, boolean buildingObject)
              throws LockingException
      {
          ContextEntry entry;
          boolean onlyDependants = !_tx.getKit().isImplicitLockingUsed();
          ClassDescriptor mif = _pb.getClassDescriptor(userObject.getClass());
  
          // N:1 relations
          Iterator iter = mif.getObjectReferenceDescriptors().iterator();
          ObjectReferenceDescriptor rds = null;
          PersistentField f;
          Object relUserObj;
          Identity relOid;
          boolean isDependent;
  
          while (iter.hasNext())
          {
              rds = (ObjectReferenceDescriptor) iter.next();
              isDependent = rds.getOtmDependent();
              if (onlyDependants && !isDependent)
              {
                  continue;
              }
              f = rds.getPersistentField();
              relUserObj = f.get(userObject);
              if (relUserObj != null)
              {
                  relOid = new Identity(relUserObj, _pb);
                  entry = (ContextEntry) _objects.get(relOid);
                  if ((entry == null) || (entry.userObject != relUserObj))
                  {
                      entry = insertInternal(relOid, relUserObj, lock, isDependent,
                                             oid, stack);
                      if (buildingObject && (entry != null))
                      {
                          f.set(userObject, entry.userObject);
                          f.set(cacheObject, entry.cacheObject);
                      }
                  }
              }
          }
  
          // 1:N relations
          Iterator collections = mif.getCollectionDescriptors().iterator();
          CollectionDescriptor cds;
          Object userCol;
          Iterator userColIterator;
          Class type;
          ArrayList newUserCol = null;
          ArrayList newCacheCol = null;
  
          while (collections.hasNext())
          {
              cds = (CollectionDescriptor) collections.next();
              f = cds.getPersistentField();
              type = f.getType();
              isDependent = cds.getOtmDependent();
              if (onlyDependants && !isDependent)
              {
                  continue;
              }
              userCol = f.get(userObject);
              if (userCol != null)
              {
                  if ((userCol instanceof CollectionProxyDefaultImpl)
                          && !((CollectionProxyDefaultImpl) userCol).isLoaded())
                  {
                      continue;
                  }
  
                  if (buildingObject)
                  {
                      newUserCol = new ArrayList();
                      newCacheCol = new ArrayList();
                  }
  
                  if (Collection.class.isAssignableFrom(type))
                  {
                      userColIterator = ((Collection) userCol).iterator();
                  }
                  else if (type.isArray())
                  {
                      userColIterator = new ArrayIterator(userCol);
                  }
                  else
                  {
                      throw new OJBRuntimeException(
                          userCol.getClass()
                              + " can not be managed by OJB OTM, use Array or Collection instead !");
                  }
  
                  while (userColIterator.hasNext())
                  {
                      relUserObj = userColIterator.next();
                      relOid = new Identity(relUserObj, _pb);
                      entry = (ContextEntry) _objects.get(relOid);
                      if ((entry == null) || (entry.userObject != relUserObj))
                      {
                          entry = insertInternal(relOid, relUserObj, lock,
                                                 isDependent, null, stack);
                      }
                      if (buildingObject && (entry != null))
                      {
                          newUserCol.add(entry.userObject);
                          newCacheCol.add(entry.cacheObject);
                      }
                  }
                  if (buildingObject)
                  {
                      setCollectionField(userObject, f, newUserCol);
                      setCollectionField(cacheObject, f, newCacheCol);
                  }
              }
          }
      }