org.infinispan.client.hotrod.event.impl.ContinuousQueryImpl Maven / Gradle / Ivy
package org.infinispan.client.hotrod.event.impl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.client.hotrod.annotation.ClientCacheEntryCreated;
import org.infinispan.client.hotrod.annotation.ClientCacheEntryExpired;
import org.infinispan.client.hotrod.annotation.ClientCacheEntryModified;
import org.infinispan.client.hotrod.annotation.ClientCacheEntryRemoved;
import org.infinispan.client.hotrod.annotation.ClientListener;
import org.infinispan.client.hotrod.event.ClientCacheEntryCustomEvent;
import org.infinispan.client.hotrod.filter.Filters;
import org.infinispan.client.hotrod.marshall.MarshallerUtil;
import org.infinispan.commons.api.query.ContinuousQueryListener;
import org.infinispan.protostream.ProtobufUtil;
import org.infinispan.protostream.SerializationContext;
import org.infinispan.query.api.continuous.ContinuousQuery;
import org.infinispan.commons.api.query.Query;
import org.infinispan.query.remote.client.impl.ContinuousQueryResult;
/**
* A container of continuous query listeners for a remote cache.
* This class is not threadsafe.
*
* @author [email protected]
* @since 8.2
*/
public final class ContinuousQueryImpl implements ContinuousQuery {
private final RemoteCache cache;
private final SerializationContext serializationContext;
private final List> listeners = new ArrayList<>();
public ContinuousQueryImpl(RemoteCache cache) {
if (cache == null) {
throw new IllegalArgumentException("cache parameter cannot be null");
}
this.cache = cache;
serializationContext = MarshallerUtil.getSerializationContext(cache.getRemoteCacheContainer());
}
@Override
public void addContinuousQueryListener(String queryString, ContinuousQueryListener listener) {
addContinuousQueryListener(queryString, null, listener);
}
@Override
public void addContinuousQueryListener(String queryString, Map namedParameters, ContinuousQueryListener listener) {
ClientEntryListener eventListener = new ClientEntryListener<>(serializationContext, listener);
Object[] factoryParams = Filters.makeFactoryParams(queryString, namedParameters);
cache.addClientListener(eventListener, factoryParams, null);
listeners.add(eventListener);
}
/**
* Registers a continuous query listener that uses a query DSL based filter. The listener will receive notifications
* when a cache entry joins or leaves the matching set defined by the query.
*
* @param listener the continuous query listener instance
* @param query the query to be used for determining the matching set
*/
public void addContinuousQueryListener(Query> query, ContinuousQueryListener listener) {
addContinuousQueryListener(query.getQueryString(), query.getParameters(), listener);
}
public void removeContinuousQueryListener(ContinuousQueryListener listener) {
for (Iterator> it = listeners.iterator(); it.hasNext(); ) {
ClientEntryListener, ?> l = it.next();
if (l.listener == listener) {
cache.removeClientListener(l);
it.remove();
break;
}
}
}
public List> getListeners() {
List> queryListeners = new ArrayList<>(listeners.size());
for (ClientEntryListener l : listeners) {
queryListeners.add(l.listener);
}
return queryListeners;
}
public void removeAllListeners() {
for (ClientEntryListener, ?> l : listeners) {
cache.removeClientListener(l);
}
listeners.clear();
}
@ClientListener(filterFactoryName = Filters.CONTINUOUS_QUERY_FILTER_FACTORY_NAME,
converterFactoryName = Filters.CONTINUOUS_QUERY_FILTER_FACTORY_NAME,
useRawData = true, includeCurrentState = true)
private static final class ClientEntryListener {
private final SerializationContext serializationContext;
private final ContinuousQueryListener listener;
ClientEntryListener(SerializationContext serializationContext, ContinuousQueryListener listener) {
this.serializationContext = serializationContext;
this.listener = listener;
}
@ClientCacheEntryCreated
@ClientCacheEntryModified
@ClientCacheEntryRemoved
@ClientCacheEntryExpired
public void handleEvent(ClientCacheEntryCustomEvent event) throws IOException {
byte[] eventData = event.getEventData();
ContinuousQueryResult cqr = ProtobufUtil.fromWrappedByteArray(serializationContext, eventData);
Object key = ProtobufUtil.fromWrappedByteArray(serializationContext, cqr.getKey());
Object value = cqr.getValue() != null ? ProtobufUtil.fromWrappedByteArray(serializationContext, cqr.getValue()) : cqr.getProjection();
switch (cqr.getResultType()) {
case JOINING:
listener.resultJoining((K) key, (C) value);
break;
case UPDATED:
listener.resultUpdated((K) key, (C) value);
break;
case LEAVING:
listener.resultLeaving((K) key);
break;
default:
throw new IllegalStateException("Unexpected result type : " + cqr.getResultType());
}
}
}
}