package org.infinispan.query.remote.impl.filter;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.infinispan.Cache;
import org.infinispan.commons.io.UnsignedNumeric;
import org.infinispan.commons.marshall.AbstractExternalizer;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.metadata.Metadata;
import org.infinispan.objectfilter.ObjectFilter;
import org.infinispan.objectfilter.impl.ProtobufMatcher;
import org.infinispan.query.dsl.embedded.impl.IckleFilterAndConverter;
import org.infinispan.query.remote.impl.CompatibilityReflectionMatcher;
import org.infinispan.query.remote.impl.ExternalizerIds;
import org.infinispan.query.remote.impl.indexing.ProtobufValueWrapper;
/**
* A subclass of JPAFilterAndConverter that is able to deal with binary values wrapped in a ProtobufValueWrapper.
*
* @author anistor@redhat.com
* @since 7.2
*/
public final class IckleProtobufFilterAndConverter extends IckleFilterAndConverter<Object, Object> {
private boolean usesValueWrapper;
private boolean isCompatMode;
public IckleProtobufFilterAndConverter(String queryString, Map<String, Object> namedParameters) {
super(queryString, namedParameters, ProtobufMatcher.class);
}
@Override
protected void injectDependencies(Cache cache) {
Configuration cfg = cache.getCacheConfiguration();
isCompatMode = cfg.compatibility().enabled();
if (isCompatMode) {
matcherImplClass = CompatibilityReflectionMatcher.class;
}
usesValueWrapper = cfg.indexing().index().isEnabled() && !isCompatMode;
super.injectDependencies(cache);
}
@Override
public ObjectFilter.FilterResult filterAndConvert(Object key, Object value, Metadata metadata) {
if (value == null) {
return null;
}
if (usesValueWrapper) {
value = ((ProtobufValueWrapper) value).getBinary();
}
return getObjectFilter().filter(value);
}
@Override
public String toString() {
return "IckleProtobufFilterAndConverter{queryString='" + getQueryString() + "'}";
}
public static final class Externalizer extends AbstractExternalizer<IckleProtobufFilterAndConverter> {
@Override
public void writeObject(ObjectOutput output, IckleProtobufFilterAndConverter filterAndConverter) throws IOException {
output.writeUTF(filterAndConverter.getQueryString());
Map<String, Object> namedParameters = filterAndConverter.getNamedParameters();
if (namedParameters != null) {
UnsignedNumeric.writeUnsignedInt(output, namedParameters.size());
for (Map.Entry<String, Object> e : namedParameters.entrySet()) {
output.writeUTF(e.getKey());
output.writeObject(e.getValue());
}
} else {
UnsignedNumeric.writeUnsignedInt(output, 0);
}
}
@Override
public IckleProtobufFilterAndConverter readObject(ObjectInput input) throws IOException, ClassNotFoundException {
String queryString = input.readUTF();
int paramsSize = UnsignedNumeric.readUnsignedInt(input);
Map<String, Object> namedParameters = null;
if (paramsSize != 0) {
namedParameters = new HashMap<>(paramsSize);
for (int i = 0; i < paramsSize; i++) {
String paramName = input.readUTF();
Object paramValue = input.readObject();
namedParameters.put(paramName, paramValue);
}
}
return new IckleProtobufFilterAndConverter(queryString, namedParameters);
}
@Override
public Integer getId() {
return ExternalizerIds.ICKLE_PROTOBUF_FILTER_AND_CONVERTER;
}
@Override
public Set<Class<? extends IckleProtobufFilterAndConverter>> getTypeClasses() {
return Collections.singleton(IckleProtobufFilterAndConverter.class);
}
}
}