public Object[] getNaturalIdSnapshot(Serializable id, EntityPersister persister)
      throws HibernateException {
    if (!persister.hasNaturalIdentifier()) {
      return null;
    }

    // if the natural-id is marked as non-mutable, it is not retrieved during a
    // normal database-snapshot operation...
    int[] props = persister.getNaturalIdentifierProperties();
    boolean[] updateable = persister.getPropertyUpdateability();
    boolean allNatualIdPropsAreUpdateable = true;
    for (int i = 0; i < props.length; i++) {
      if (!updateable[props[i]]) {
        allNatualIdPropsAreUpdateable = false;
        break;
      }
    }

    if (allNatualIdPropsAreUpdateable) {
      // do this when all the properties are updateable since there is
      // a certain likelihood that the information will already be
      // snapshot-cached.
      Object[] entitySnapshot = getDatabaseSnapshot(id, persister);
      if (entitySnapshot == NO_ROW) {
        return null;
      }
      Object[] naturalIdSnapshot = new Object[props.length];
      for (int i = 0; i < props.length; i++) {
        naturalIdSnapshot[i] = entitySnapshot[props[i]];
      }
      return naturalIdSnapshot;
    } else {
      return persister.getNaturalIdentifierSnapshot(id, session);
    }
  }
 private void checkNaturalId(
     EntityPersister persister,
     EntityEntry entry,
     Object[] current,
     Object[] loaded,
     EntityMode entityMode,
     SessionImplementor session) {
   if (persister.hasNaturalIdentifier() && entry.getStatus() != Status.READ_ONLY) {
     Object[] snapshot = null;
     Type[] types = persister.getPropertyTypes();
     int[] props = persister.getNaturalIdentifierProperties();
     boolean[] updateable = persister.getPropertyUpdateability();
     for (int i = 0; i < props.length; i++) {
       int prop = props[i];
       if (!updateable[prop]) {
         Object loadedVal;
         if (loaded == null) {
           if (snapshot == null) {
             snapshot =
                 session.getPersistenceContext().getNaturalIdSnapshot(entry.getId(), persister);
           }
           loadedVal = snapshot[i];
         } else {
           loadedVal = loaded[prop];
         }
         if (!types[prop].isEqual(current[prop], loadedVal, entityMode)) {
           throw new HibernateException(
               "immutable natural identifier of an instance of "
                   + persister.getEntityName()
                   + " was altered");
         }
       }
     }
   }
 }
  private Object[] determinePreviousNaturalIdValues(
      EntityPersister persister,
      Object[] previousState,
      SessionImplementor session,
      Serializable id) {
    if (!persister.hasNaturalIdentifier()) {
      return null;
    }

    if (previousState != null) {
      return session
          .getPersistenceContext()
          .getNaturalIdHelper()
          .extractNaturalIdValues(previousState, persister);
    }

    return session.getPersistenceContext().getNaturalIdSnapshot(id, persister);
  }