private void raiseEventForInitialTransfer(UUID identifier, CacheEntry entry, boolean clustered) {
    EventImpl preEvent;
    if (clustered) {
      // In clustered mode we only send post event
      preEvent = null;
    } else {
      preEvent = EventImpl.createEvent(cache, CACHE_ENTRY_CREATED);
      preEvent.setKey(entry.getKey());
      preEvent.setPre(true);
    }

    EventImpl postEvent = EventImpl.createEvent(cache, CACHE_ENTRY_CREATED);
    postEvent.setKey(entry.getKey());
    postEvent.setValue(entry.getValue());
    postEvent.setMetadata(entry.getMetadata());
    postEvent.setPre(false);

    for (CacheEntryListenerInvocation<K, V> invocation : cacheEntryCreatedListeners) {
      // Now notify all our methods of the creates
      if (invocation.getIdentifier() == identifier) {
        if (preEvent != null) {
          // Non clustered notifications are done twice
          invocation.invokeNoChecks(preEvent, true, true);
        }
        invocation.invokeNoChecks(postEvent, true, true);
      }
    }
  }
 @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 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 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 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();
     }
   }
 }
  @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);
    }
  }
 private void registerClusterListenerCallablesToInstall(
     Set<Object> enlistedAlready,
     Set<DistributedCallable> callables,
     List<CacheEntryListenerInvocation<K, V>> listenerInvocations) {
   for (CacheEntryListenerInvocation<K, V> listener : listenerInvocations) {
     if (!enlistedAlready.contains(listener.getTarget())) {
       // If clustered means it is local - so use our address
       if (listener.isClustered()) {
         callables.add(
             new ClusterListenerReplicateCallable(
                 listener.getIdentifier(),
                 cache.getCacheManager().getAddress(),
                 listener.getFilter(),
                 listener.getConverter(),
                 listener.isSync()));
         enlistedAlready.add(listener.getTarget());
       } else if (listener.getTarget() instanceof RemoteClusterListener) {
         RemoteClusterListener lcl = (RemoteClusterListener) listener.getTarget();
         callables.add(
             new ClusterListenerReplicateCallable(
                 lcl.getId(),
                 lcl.getOwnerAddress(),
                 listener.getFilter(),
                 listener.getConverter(),
                 listener.isSync()));
         enlistedAlready.add(listener.getTarget());
       }
     }
   }
 }
 @Override
 public void notifyClusterListeners(
     Collection<? extends CacheEntryEvent<K, V>> events, UUID uuid) {
   for (CacheEntryEvent<K, V> event : events) {
     if (event.isPre()) {
       throw new IllegalArgumentException(
           "Events for cluster listener should never be pre change");
     }
     switch (event.getType()) {
       case CACHE_ENTRY_MODIFIED:
         for (CacheEntryListenerInvocation<K, V> listener : cacheEntryModifiedListeners) {
           if (listener.isClustered() && uuid.equals(listener.getIdentifier())) {
             // We force invocation, since it means the owning node passed filters already and they
             // already converted so don't run converter either
             listener.invokeNoChecks(event, false, true);
           }
         }
         break;
       case CACHE_ENTRY_CREATED:
         for (CacheEntryListenerInvocation<K, V> listener : cacheEntryCreatedListeners) {
           if (listener.isClustered() && uuid.equals(listener.getIdentifier())) {
             // We force invocation, since it means the owning node passed filters already and they
             // already converted so don't run converter either
             listener.invokeNoChecks(event, false, true);
           }
         }
         break;
       case CACHE_ENTRY_REMOVED:
         for (CacheEntryListenerInvocation<K, V> listener : cacheEntryRemovedListeners) {
           if (listener.isClustered() && uuid.equals(listener.getIdentifier())) {
             // We force invocation, since it means the owning node passed filters already and they
             // already converted so don't run converter either
             listener.invokeNoChecks(event, false, true);
           }
         }
         break;
       default:
         throw new IllegalArgumentException("Unexpected event type encountered!");
     }
   }
 }