package org.infinispan.query.remote.impl; import java.util.Arrays; import java.util.Collections; import java.util.Map; import java.util.Set; import org.apache.lucene.index.Term; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; import org.hibernate.search.query.engine.spi.HSQuery; import org.hibernate.search.spi.CustomTypeMetadata; import org.infinispan.AdvancedCache; import org.infinispan.objectfilter.impl.ProtobufMatcher; import org.infinispan.objectfilter.impl.syntax.parser.IckleParsingResult; import org.infinispan.protostream.descriptors.Descriptor; import org.infinispan.query.CacheQuery; import org.infinispan.query.dsl.embedded.impl.IckleFilterAndConverter; import org.infinispan.query.dsl.embedded.impl.RowProcessor; import org.infinispan.query.impl.SearchManagerImpl; import org.infinispan.query.remote.impl.filter.IckleProtobufFilterAndConverter; import org.infinispan.query.remote.impl.indexing.IndexingMetadata; import org.infinispan.query.remote.impl.indexing.ProtobufValueWrapper; /** * @author anistor@redhat.com * @since 8.0 */ final class RemoteQueryEngine extends BaseRemoteQueryEngine { RemoteQueryEngine(AdvancedCache<?, ?> cache, boolean isIndexed) { super(cache, isIndexed, ProtobufMatcher.class, new ProtobufFieldBridgeAndAnalyzerProvider()); } @Override protected RowProcessor makeProjectionProcessor(Class<?>[] projectedTypes) { // Protobuf's booleans are indexed as Strings, so we need to convert them. // Collect here the positions of all Boolean projections. int[] pos = new int[projectedTypes.length]; int len = 0; for (int i = 0; i < projectedTypes.length; i++) { if (projectedTypes[i] == Boolean.class) { pos[len++] = i; } } if (len == 0) { return null; } final int[] cols = len < pos.length ? Arrays.copyOf(pos, len) : pos; return row -> { for (int i : cols) { if (row[i] != null) { // the Boolean column is actually encoded as a String, so we convert it row[i] = "true".equals(row[i]); } } return row; }; } @Override protected Query makeTypeQuery(Query query, String targetEntityName) { return new BooleanQuery.Builder() .add(new TermQuery(new Term(QueryFacadeImpl.TYPE_FIELD_NAME, targetEntityName)), BooleanClause.Occur.FILTER) .add(query, BooleanClause.Occur.MUST) .build(); } @Override protected CacheQuery<?> makeCacheQuery(IckleParsingResult<Descriptor> ickleParsingResult, Query luceneQuery) { CustomTypeMetadata customTypeMetadata = new CustomTypeMetadata() { @Override public Class<?> getEntityType() { return ProtobufValueWrapper.class; } @Override public Set<String> getSortableFields() { IndexingMetadata indexingMetadata = ickleParsingResult.getTargetEntityMetadata().getProcessedAnnotation(IndexingMetadata.INDEXED_ANNOTATION); return indexingMetadata != null ? indexingMetadata.getSortableFields() : Collections.emptySet(); } }; HSQuery hSearchQuery = getSearchFactory().createHSQuery(luceneQuery, customTypeMetadata); return ((SearchManagerImpl) getSearchManager()).getQuery(hSearchQuery); } @Override protected IckleFilterAndConverter createFilter(String queryString, Map<String, Object> namedParameters) { return isIndexed ? new IckleProtobufFilterAndConverter(queryString, namedParameters) : super.createFilter(queryString, namedParameters); } @Override protected Class<?> getTargetedClass(IckleParsingResult<?> parsingResult) { return ProtobufValueWrapper.class; } }