/**
   * If the existing proxy is insufficiently "narrow" (derived), instantiate a new proxy and
   * overwrite the registration of the old one. This breaks == and occurs only for "class" proxies
   * rather than "interface" proxies. Also init the proxy to point to the given target
   * implementation if necessary.
   *
   * @param proxy The proxy instance to be narrowed.
   * @param persister The persister for the proxied entity.
   * @param key The internal cache key for the proxied entity.
   * @param object (optional) the actual proxied entity instance.
   * @return An appropriately narrowed instance.
   * @throws HibernateException
   */
  public Object narrowProxy(Object proxy, EntityPersister persister, EntityKey key, Object object)
      throws HibernateException {

    boolean alreadyNarrow =
        persister.getConcreteProxyClass(session.getEntityMode()).isAssignableFrom(proxy.getClass());

    if (!alreadyNarrow) {
      if (PROXY_WARN_LOG.isWarnEnabled()) {
        PROXY_WARN_LOG.warn(
            "Narrowing proxy to "
                + persister.getConcreteProxyClass(session.getEntityMode())
                + " - this operation breaks ==");
      }

      if (object != null) {
        proxiesByKey.remove(key);
        return object; // return the proxied object
      } else {
        proxy = persister.createProxy(key.getIdentifier(), session);
        proxiesByKey.put(key, proxy); // overwrite old proxy
        return proxy;
      }

    } else {

      if (object != null) {
        LazyInitializer li = ((HibernateProxy) proxy).getHibernateLazyInitializer();
        li.setImplementation(object);
      }

      return proxy;
    }
  }
 @Override
 public void setImplementation(Object target) {
   LazyInitializer rawLazyInitializer = this.lazyInitializer;
   Object oldTarget =
       rawLazyInitializer.isUninitialized() ? null : rawLazyInitializer.getImplementation();
   if (target != oldTarget) {
     ScalarListener listener = this.new TargetScalarListener();
     if (oldTarget != null) {
       this.omFactory.get(oldTarget).removeScalarListener(listener);
     }
     rawLazyInitializer.setImplementation(target);
     this.oldTarget = target;
     if (target != null) {
       ObjectModel targetOM = this.omFactory.get(target);
       targetOM.removeScalarListener(listener); // remove the duplicated listener.
       targetOM.addScalarListener(listener);
     }
   }
 }