/*
* Copyright 2014, Tuplejump Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.tuplejump.stargate.cassandra;
import com.google.common.collect.TreeMultimap;
import com.tuplejump.stargate.lucene.IndexEntryCollector;
import com.tuplejump.stargate.lucene.IndexEntryCollector.IndexEntry;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.DecoratedKey;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.Composite;
import org.apache.cassandra.db.filter.ColumnSlice;
import org.apache.cassandra.db.filter.ExtendedFilter;
import org.apache.cassandra.db.filter.QueryFilter;
import org.apache.cassandra.db.filter.SliceQueryFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* User: satya
* A mapper which helps in reading the actual rows from Cassandra using the search results
*/
public class ResultMapper {
public static final Logger logger = LoggerFactory.getLogger(SearchSupport.class);
public final ExtendedFilter filter;
public final IndexEntryCollector collector;
public final int limit;
public final boolean showScore;
public final TableMapper tableMapper;
public final SearchSupport searchSupport;
public ResultMapper(TableMapper tableMapper, SearchSupport searchSupport, ExtendedFilter filter, IndexEntryCollector collector, boolean showScore) throws Exception {
this.tableMapper = tableMapper;
this.searchSupport = searchSupport;
this.filter = filter;
this.collector = collector;
this.limit = filter.currentLimit();
this.showScore = showScore;
}
public Map<CellName, ColumnFamily> fetchRangeSlice(Collection<IndexEntry> entries, DecoratedKey dk) {
return getCellNameColumnFamilyMap(dk, getColumnSlices(entries));
}
public TreeMultimap docsByRowKey() {
return collector.docsByRowKey();
}
public List<IndexEntry> docs() {
return collector.docs();
}
private ColumnSlice[] getColumnSlices(Collection<IndexEntry> entries) {
ColumnSlice[] columnSlices = new ColumnSlice[entries.size()];
int i = 0;
for (IndexEntry entry : entries) {
Composite start = tableMapper.start(entry.clusteringKey);
Composite end = tableMapper.end(start);
ColumnSlice columnSlice = new ColumnSlice(start, end);
columnSlices[i++] = columnSlice;
}
return columnSlices;
}
public Map<CellName, ColumnFamily> fetchPagedRangeSlice(Collection<IndexEntry> entries, DecoratedKey dk, int pageSize) {
return getCellNameColumnFamilyMap(dk, getPagedColumnSlices(dk, entries, pageSize));
}
private ColumnSlice[] getPagedColumnSlices(DecoratedKey dk, Collection<IndexEntry> entries, int pageSize) {
ArrayList<ColumnSlice> columnSlices = new ArrayList<>(Math.min(entries.size(), pageSize));
for (IndexEntry entry : entries) {
CellName cellName = entry.clusteringKey;
if (!filter.columnFilter(dk.getKey()).maySelectPrefix(tableMapper.table.getComparator(), cellName.start())) {
continue;
}
Composite start = tableMapper.start(cellName);
Composite end = tableMapper.end(start);
ColumnSlice columnSlice = new ColumnSlice(start, end);
columnSlices.add(columnSlice);
if (columnSlices.size() == pageSize) {
break;
}
}
return columnSlices.toArray(new ColumnSlice[columnSlices.size()]);
}
private Map<CellName, ColumnFamily> getCellNameColumnFamilyMap(DecoratedKey dk, ColumnSlice[] columnSlices) {
SliceQueryFilter sliceQueryFilter = new SliceQueryFilter(columnSlices, false, Integer.MAX_VALUE);
QueryFilter queryFilter = new QueryFilter(dk, tableMapper.table.name, sliceQueryFilter, filter.timestamp);
ColumnFamily columnFamily = tableMapper.table.getColumnFamily(queryFilter);
return tableMapper.getRows(columnFamily);
}
}