/**
   * Based on configured options, will either return a pre-existing proxy, generate a new proxy, or
   * perform an actual load.
   *
   * @return The result of the proxy/load operation.
   * @throws HibernateException
   */
  protected Object proxyOrLoad(
      final LoadEvent event,
      final EntityPersister persister,
      final EntityKey keyToLoad,
      final LoadEventListener.LoadType options)
      throws HibernateException {

    if (log.isTraceEnabled()) {
      log.trace(
          "loading entity: "
              + MessageHelper.infoString(
                  persister, event.getEntityId(), event.getSession().getFactory()));
    }

    if (!persister.hasProxy()) {
      // this class has no proxies (so do a shortcut)
      return load(event, persister, keyToLoad, options);
    } else {
      final PersistenceContext persistenceContext = event.getSession().getPersistenceContext();

      // look for a proxy
      Object proxy = persistenceContext.getProxy(keyToLoad);
      if (proxy != null) {
        return returnNarrowedProxy(event, persister, keyToLoad, options, persistenceContext, proxy);
      } else {
        if (options.isAllowProxyCreation()) {
          return createProxyIfNecessary(event, persister, keyToLoad, options, persistenceContext);
        } else {
          // return a newly loaded object
          return load(event, persister, keyToLoad, options);
        }
      }
    }
  }
 /**
  * Return the existing proxy associated with the given <tt>EntityKey</tt>, or the third argument
  * (the entity associated with the key) if no proxy exists. Init the proxy to the target
  * implementation, if necessary.
  */
 public Object proxyFor(EntityPersister persister, EntityKey key, Object impl)
     throws HibernateException {
   if (!persister.hasProxy()) return impl;
   Object proxy = proxiesByKey.get(key);
   if (proxy != null) {
     return narrowProxy(proxy, persister, key, impl);
   } else {
     return impl;
   }
 }
 /**
  * Does the mapping, and Hibernate default semantics, specify that this association should be
  * fetched by outer joining
  */
 protected boolean isJoinedFetchEnabledInMapping(FetchMode config, AssociationType type)
     throws MappingException {
   if (!type.isEntityType() && !type.isCollectionType()) {
     return false;
   } else {
     if (config == FetchMode.JOIN) return true;
     if (config == FetchMode.SELECT) return false;
     if (type.isEntityType()) {
       // TODO: look at the owning property and check that it
       //      isn't lazy (by instrumentation)
       EntityType entityType = (EntityType) type;
       EntityPersister persister =
           getFactory().getEntityPersister(entityType.getAssociatedEntityName());
       return !persister.hasProxy();
     } else {
       return false;
     }
   }
 }