protected void propertyConcurrentModificationCheck(
      AuditConfiguration auditConfiguration,
      Session session,
      AuditEvent e,
      Long loadAuditTransactionId,
      AuditObject auditObject) {
    List<AuditTypeField> fieldsToCheck = new ArrayList<AuditTypeField>();
    for (AuditObjectProperty auditObjectProperty : auditObject.getAuditObjectProperties()) {
      fieldsToCheck.add(auditObjectProperty.getAuditField());
    }

    if (fieldsToCheck.isEmpty()) {
      // there are no fields that we are going to modify - this means that the event is a delete
      // event for the whole object - include all properties
      fieldsToCheck.addAll(auditObject.getAuditType().getAuditFields());
    }

    List<AuditTypeField> modifiedAuditTypeFields =
        getModifiedAuditTypeFields(session, e, loadAuditTransactionId, fieldsToCheck);
    Iterator<AuditTypeField> modifiedAuditTypeFieldsIterator = modifiedAuditTypeFields.iterator();

    if (modifiedAuditTypeFieldsIterator.hasNext()) {
      AuditTypeField firstDetectedmodifiedAuditTypeField = modifiedAuditTypeFieldsIterator.next();

      if (ConcurrentModificationBehavior.THROW_EXCEPTION.equals(
          auditConfiguration
              .getExtensionManager()
              .getConcurrentModificationProvider()
              .getCheckBehavior())) {
        if (session.getTransaction().isActive()) {
          session.getTransaction().rollback();
        }
        throw new PropertyConcurrentModificationException(
            firstDetectedmodifiedAuditTypeField.getOwnerType().getClassName(),
            firstDetectedmodifiedAuditTypeField.getName(),
            firstDetectedmodifiedAuditTypeField.getOwnerType().getLabel(),
            firstDetectedmodifiedAuditTypeField.getLabel(),
            e.getEntityId());
      } else if (ConcurrentModificationBehavior.LOG.equals(
          auditConfiguration
              .getExtensionManager()
              .getConcurrentModificationProvider()
              .getCheckBehavior())) {
        if (log.isWarnEnabled()) {
          log.warn(
              "Concurrent modification detected: className="
                  + firstDetectedmodifiedAuditTypeField.getOwnerType().getClassName()
                  + ",field name="
                  + firstDetectedmodifiedAuditTypeField.getName()
                  + ",class label="
                  + firstDetectedmodifiedAuditTypeField.getOwnerType().getLabel()
                  + ",field label="
                  + firstDetectedmodifiedAuditTypeField.getLabel()
                  + ",entity id="
                  + e.getEntityId());
        }
      }
    }
  }
  protected void entityConcurrentModificationCheck(
      AuditConfiguration auditConfiguration,
      Session session,
      Long loadAuditTransactionId,
      AuditObject auditObject) {
    AuditType auditType = null;
    String targetEntityId = null;

    if (auditObject instanceof EntityAuditObject) {
      // only check the entities - the components are
      // going to be check on field level check
      EntityAuditObject entityAuditObject = (EntityAuditObject) auditObject;
      auditType = entityAuditObject.getAuditType();
      targetEntityId = entityAuditObject.getTargetEntityId();
    } else {
      ComponentAuditObject component = (ComponentAuditObject) auditObject;
      AuditObject entity = component.getParentAuditObject();

      while (entity != null && entity instanceof ComponentAuditObject) {
        entity = ((ComponentAuditObject) entity).getParentAuditObject();
      }

      auditType = component.getAuditType();
      targetEntityId = ((EntityAuditObject) entity).getTargetEntityId();
    }

    Long latestEntityTransactionId =
        HibernateAudit.getLatestAuditTransactionIdByEntityAndAfterAuditTransactionId(
            session, auditType, targetEntityId, loadAuditTransactionId);
    if (latestEntityTransactionId != null
        && !latestEntityTransactionId.equals(loadAuditTransactionId)) {
      if (ConcurrentModificationBehavior.THROW_EXCEPTION.equals(
          auditConfiguration
              .getExtensionManager()
              .getConcurrentModificationProvider()
              .getCheckBehavior())) {
        if (session.getTransaction().isActive()) {
          session.getTransaction().rollback();
        }
        throw new ObjectConcurrentModificationException(
            auditType.getClassName(), auditType.getLabel(), targetEntityId);
      } else if (ConcurrentModificationBehavior.LOG.equals(
          auditConfiguration
              .getExtensionManager()
              .getConcurrentModificationProvider()
              .getCheckBehavior())) {
        if (log.isWarnEnabled()) {
          log.warn(
              "Concurrent modification detected: className="
                  + auditType.getClassName()
                  + ",label="
                  + auditType.getLabel()
                  + ",targetEntityId="
                  + targetEntityId);
        }
      }
    }
  }