@Override
  public void notifyCacheEntriesEvicted(
      Collection<InternalCacheEntry<? extends K, ? extends V>> entries,
      InvocationContext ctx,
      FlagAffectedCommand command) {
    if (!entries.isEmpty()) {
      if (isNotificationAllowed(command, cacheEntriesEvictedListeners)) {
        EventImpl<K, V> e = EventImpl.createEvent(cache, CACHE_ENTRY_EVICTED);
        Map<K, V> evictedKeysAndValues =
            transformCollectionToMap(
                entries,
                new InfinispanCollections.MapMakerFunction<
                    K, V, InternalCacheEntry<? extends K, ? extends V>>() {
                  @Override
                  public Map.Entry<K, V> transform(
                      final InternalCacheEntry<? extends K, ? extends V> input) {
                    return new Map.Entry<K, V>() {
                      @Override
                      public K getKey() {
                        return input.getKey();
                      }

                      @Override
                      public V getValue() {
                        return input.getValue();
                      }

                      @Override
                      public V setValue(V value) {
                        throw new UnsupportedOperationException();
                      }
                    };
                  }
                });

        e.setEntries(evictedKeysAndValues);
        for (CacheEntryListenerInvocation<K, V> listener : cacheEntriesEvictedListeners)
          listener.invoke(e);
      }

      // For backward compat
      if (isNotificationAllowed(command, cacheEntryEvictedListeners)) {
        for (InternalCacheEntry<? extends K, ? extends V> ice : entries) {
          EventImpl<K, V> e = EventImpl.createEvent(cache, CACHE_ENTRY_EVICTED);
          e.setKey(ice.getKey());
          e.setValue(ice.getValue());
          boolean isLocalNodePrimaryOwner =
              clusteringDependentLogic.localNodeIsPrimaryOwner(ice.getKey());
          for (CacheEntryListenerInvocation<K, V> listener : cacheEntryEvictedListeners)
            listener.invoke(e, isLocalNodePrimaryOwner);
        }
      }
    }
  }
 @Override
 public void notifyPartitionStatusChanged(AvailabilityMode mode, boolean pre) {
   if (!partitionChangedListeners.isEmpty()) {
     EventImpl<K, V> e = EventImpl.createEvent(cache, PARTITION_STATUS_CHANGED);
     e.setPre(pre);
     e.setAvailabilityMode(mode);
     for (CacheEntryListenerInvocation<K, V> listener : partitionChangedListeners)
       listener.invoke(e);
   }
 }
 @Override
 public void notifyTransactionRegistered(
     GlobalTransaction globalTransaction, boolean isOriginLocal) {
   if (!transactionRegisteredListeners.isEmpty()) {
     EventImpl<K, V> e = EventImpl.createEvent(cache, TRANSACTION_REGISTERED);
     e.setOriginLocal(isOriginLocal);
     e.setTransactionId(globalTransaction);
     for (CacheEntryListenerInvocation<K, V> listener : transactionRegisteredListeners)
       listener.invoke(e);
   }
 }
 @Override
 public void notifyCacheEntryInvalidated(
     final K key, V value, final boolean pre, InvocationContext ctx, FlagAffectedCommand command) {
   if (isNotificationAllowed(command, cacheEntryInvalidatedListeners)) {
     EventImpl<K, V> e = EventImpl.createEvent(cache, CACHE_ENTRY_INVALIDATED);
     configureEvent(e, key, value, pre, ctx, command, value, null);
     setTx(ctx, e);
     boolean isLocalNodePrimaryOwner = clusteringDependentLogic.localNodeIsPrimaryOwner(key);
     for (CacheEntryListenerInvocation<K, V> listener : cacheEntryInvalidatedListeners)
       listener.invoke(e, isLocalNodePrimaryOwner);
   }
 }
  @Override
  public void notifyCacheEntryEvicted(
      K key, V value, InvocationContext ctx, FlagAffectedCommand command) {
    boolean isLocalNodePrimaryOwner = clusteringDependentLogic.localNodeIsPrimaryOwner(key);
    if (isNotificationAllowed(command, cacheEntriesEvictedListeners)) {
      EventImpl<K, V> e = EventImpl.createEvent(cache, CACHE_ENTRY_EVICTED);
      Map<K, V> map = Collections.singletonMap(key, value);
      e.setEntries(map);
      for (CacheEntryListenerInvocation<K, V> listener : cacheEntriesEvictedListeners)
        listener.invoke(e, isLocalNodePrimaryOwner);
    }

    // For backward compat
    if (isNotificationAllowed(command, cacheEntryEvictedListeners)) {
      EventImpl<K, V> e = EventImpl.createEvent(cache, CACHE_ENTRY_EVICTED);
      e.setKey(key);
      e.setValue(value);
      for (CacheEntryListenerInvocation<K, V> listener : cacheEntryEvictedListeners)
        listener.invoke(e, isLocalNodePrimaryOwner);
    }
  }
 @Override
 public void notifyCacheEntryPassivated(
     K key, V value, boolean pre, InvocationContext ctx, FlagAffectedCommand command) {
   if (isNotificationAllowed(command, cacheEntryPassivatedListeners)) {
     EventImpl<K, V> e = EventImpl.createEvent(cache, CACHE_ENTRY_PASSIVATED);
     e.setPre(pre);
     e.setKey(key);
     e.setValue(value);
     boolean isLocalNodePrimaryOwner = clusteringDependentLogic.localNodeIsPrimaryOwner(key);
     for (CacheEntryListenerInvocation<K, V> listener : cacheEntryPassivatedListeners)
       listener.invoke(e, isLocalNodePrimaryOwner);
   }
 }
 @Override
 public void notifyCacheEntryCreated(
     K key, V value, boolean pre, InvocationContext ctx, FlagAffectedCommand command) {
   if (!cacheEntryCreatedListeners.isEmpty()) {
     EventImpl<K, V> e = EventImpl.createEvent(cache, CACHE_ENTRY_CREATED);
     configureEvent(e, key, value, pre, ctx, command, null, null);
     boolean isLocalNodePrimaryOwner = clusteringDependentLogic.localNodeIsPrimaryOwner(key);
     for (CacheEntryListenerInvocation<K, V> listener : cacheEntryCreatedListeners)
       listener.invoke(e, isLocalNodePrimaryOwner);
     if (!ctx.isInTxScope()) {
       eventManager.sendEvents();
     }
   }
 }
 @Override
 public void notifyTopologyChanged(
     CacheTopology oldTopology, CacheTopology newTopology, int newTopologyId, boolean pre) {
   if (!topologyChangedListeners.isEmpty()) {
     EventImpl<K, V> e = EventImpl.createEvent(cache, TOPOLOGY_CHANGED);
     e.setPre(pre);
     if (oldTopology != null) {
       e.setConsistentHashAtStart(oldTopology.getReadConsistentHash());
     }
     e.setConsistentHashAtEnd(newTopology.getWriteConsistentHash());
     e.setNewTopologyId(newTopologyId);
     for (CacheEntryListenerInvocation<K, V> listener : topologyChangedListeners)
       listener.invoke(e);
   }
 }
 @Override
 public void notifyDataRehashed(
     ConsistentHash readCH,
     ConsistentHash writeCH,
     ConsistentHash unionCH,
     int newTopologyId,
     boolean pre) {
   if (!dataRehashedListeners.isEmpty()) {
     EventImpl<K, V> e = EventImpl.createEvent(cache, DATA_REHASHED);
     e.setPre(pre);
     e.setConsistentHashAtStart(readCH);
     e.setConsistentHashAtEnd(writeCH);
     e.setUnionConsistentHash(unionCH);
     e.setNewTopologyId(newTopologyId);
     for (CacheEntryListenerInvocation<K, V> listener : dataRehashedListeners) listener.invoke(e);
   }
 }
 @Override
 public void notifyTransactionCompleted(
     GlobalTransaction transaction, boolean successful, InvocationContext ctx) {
   if (!transactionCompletedListeners.isEmpty()) {
     boolean isOriginLocal = ctx.isOriginLocal();
     EventImpl<K, V> e = EventImpl.createEvent(cache, TRANSACTION_COMPLETED);
     e.setOriginLocal(isOriginLocal);
     e.setTransactionId(transaction);
     e.setTransactionSuccessful(successful);
     for (CacheEntryListenerInvocation<K, V> listener : transactionCompletedListeners)
       listener.invoke(e);
     if (ctx.isInTxScope()) {
       if (successful) {
         eventManager.sendEvents();
       } else {
         eventManager.dropEvents();
       }
     }
   }
 }
 @Override
 public void notifyCacheEntryRemoved(
     K key,
     V previousValue,
     Metadata previousMetadata,
     boolean pre,
     InvocationContext ctx,
     FlagAffectedCommand command) {
   if (isNotificationAllowed(command, cacheEntryRemovedListeners)) {
     EventImpl<K, V> e = EventImpl.createEvent(cache, CACHE_ENTRY_REMOVED);
     configureEvent(e, key, null, pre, ctx, command, previousValue, previousMetadata);
     setTx(ctx, e);
     boolean isLocalNodePrimaryOwner = clusteringDependentLogic.localNodeIsPrimaryOwner(key);
     for (CacheEntryListenerInvocation<K, V> listener : cacheEntryRemovedListeners)
       listener.invoke(e, isLocalNodePrimaryOwner);
     if (!ctx.isInTxScope()) {
       eventManager.sendEvents();
     }
   }
 }