document.write('
Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. public sealed class ValidationEventListener :
  2.   RegistrableListener,
  3.   IFlushEntityEventListener,
  4.   ISaveOrUpdateEventListener,
  5.   IMergeEventListener
  6.  {
  7.   public Action<List<string>> ProcessValidationErrorsAs { get; set; }
  8.  
  9.   public ValidationEventListener(Action<List<string>> processValidationErrorsAs)
  10.   {
  11.    ProcessValidationErrorsAs = processValidationErrorsAs;
  12.   }
  13.   /// <summary>
  14.   /// Entity was flushed.
  15.   /// Event is intersected, entity is being validated in case it supports validation
  16.   /// </summary>
  17.   /// <param name="event"></param>
  18.   public void OnFlushEntity(FlushEntityEvent @event)
  19.   {
  20.    //Don\'t update if the target state is deleted
  21.    if (@event.EntityEntry.Status == Status.Deleted)
  22.     return;
  23.  
  24.    //Attempt casting the entity
  25.    IValidatable asValidatable = @event.Entity as IValidatable;
  26.  
  27.    //Entity is not IValidatable
  28.    if (asValidatable == null)
  29.     return;
  30.  
  31.    //Check for dirty properties
  32.    if (HasDirtyProperties(@event))
  33.    {
  34.     ProcessValidatableInternal(asValidatable);
  35.    }
  36.    //Hook in if this is a new entry
  37.    if (!@event.EntityEntry.ExistsInDatabase)
  38.    {
  39.     ExplicitInsertCall(asValidatable);
  40.    }
  41.   }
  42.   /// <summary>
  43.   /// Entity is being saved or updated. Executes explicit update
  44.   /// </summary>
  45.   /// <param name="event"></param>
  46.   public void OnSaveOrUpdate(SaveOrUpdateEvent @event)
  47.   {
  48.    ExplicitUpdateCall(@event.Entity as IValidatable);
  49.   }
  50.   /// <summary>
  51.   /// Entity is being merged. Executes explicit update
  52.   /// </summary>
  53.   /// <param name="event"></param>
  54.   public void OnMerge(MergeEvent @event)
  55.   {
  56.    //WARN @event.Entity is null
  57.    ExplicitUpdateCall(@event.Original as IValidatable);
  58.   }
  59.   /// <summary>
  60.   /// Entity is being merged. Executes explicit update
  61.   /// </summary>
  62.   /// <param name="event"></param>
  63.   /// <param name="copiedAlready"></param>
  64.   public void OnMerge(MergeEvent @event, IDictionary copiedAlready)
  65.   {
  66.    ExplicitUpdateCall(@event.Original as IValidatable);
  67.   }
  68.   /// <summary>
  69.   /// Explicit update call is being executed. Entity is being validated if it supports validation
  70.   /// </summary>
  71.   /// <param name="asTimeStampable"></param>
  72.   void ExplicitUpdateCall(IValidatable asValidatable)
  73.   {
  74.    //Entity is not IValidatable
  75.    if (asValidatable == null)
  76.     return;
  77.  
  78.    ProcessValidatableInternal(asValidatable);
  79.   }
  80.   /// <summary>
  81.   /// Explicit insert call is being executed. Entity is being validated if it supports validation
  82.   /// </summary>
  83.   /// <param name="asTimeStampable"></param>
  84.   void ExplicitInsertCall(IValidatable asValidatable)
  85.   {
  86.    //Entity is not IValidatable
  87.    if (asValidatable == null)
  88.     return;
  89.  
  90.    ProcessValidatableInternal(asValidatable);
  91.   }
  92.   /// <summary>
  93.   /// Processes the validatable entity
  94.   /// </summary>
  95.   /// <param name="asValidatable"></param>
  96.   void ProcessValidatableInternal(IValidatable asValidatable)
  97.   {
  98.    var result = asValidatable.Validator.ValidateBeforePersist(asValidatable);
  99.    if (!result.IsValid)
  100.    {
  101.     ProcessValidationErrorsAs(result);
  102.    }
  103.   }
  104.   /// <summary>
  105.   /// Determines whether the entity contains any dirty properties
  106.   /// </summary>
  107.   /// <param name="event"></param>
  108.   /// <returns></returns>
  109.   static bool HasDirtyProperties(FlushEntityEvent @event)
  110.   {
  111.    //Create shortcuts
  112.    ISessionImplementor session = @event.Session;
  113.    EntityEntry entry = @event.EntityEntry;
  114.    object entity = @event.Entity;
  115.  
  116.    //Checks if the entity coming with explicit parameters not to check dirty properties,
  117.    //does not exists in database yet (dirty properties cannot be set)
  118.    //or not loaded (unloaded from session explicitly)
  119.    if (!entry.RequiresDirtyCheck(entity) || !entry.ExistsInDatabase || entry.LoadedState == null)
  120.     return false;
  121.  
  122.    IEntityPersister persister = entry.Persister;
  123.  
  124.    object[] currentState = persister.GetPropertyValues(entity, session.EntityMode);
  125.  
  126.    object[] loadedState = entry.LoadedState;
  127.  
  128.    //Checks for dirty properties
  129.    return persister.EntityMetamodel.Properties
  130.     .Where((property, i) =>
  131.      !LazyPropertyInitializer.UnfetchedProperty.Equals(currentState[i])
  132.      && property.Type.IsDirty(loadedState[i], currentState[i], session)
  133.     )
  134.     .Any();
  135.   }
  136.  }
');