com.googlecode.cqengine.index.compound.CompoundIndex Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cqengine Show documentation
Show all versions of cqengine Show documentation
Collection Query Engine: NoSQL indexing and query engine for Java collections with ultra-low latency
/**
* Copyright 2012-2015 Niall Gallagher
*
* 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.googlecode.cqengine.index.compound;
import com.googlecode.cqengine.attribute.Attribute;
import com.googlecode.cqengine.index.support.AbstractMapBasedAttributeIndex;
import com.googlecode.cqengine.index.support.Factory;
import com.googlecode.cqengine.index.support.KeyStatisticsAttributeIndex;
import com.googlecode.cqengine.index.compound.support.CompoundAttribute;
import com.googlecode.cqengine.index.compound.support.CompoundQuery;
import com.googlecode.cqengine.index.compound.support.CompoundValueTuple;
import com.googlecode.cqengine.index.support.CloseableIterable;
import com.googlecode.cqengine.quantizer.Quantizer;
import com.googlecode.cqengine.query.Query;
import com.googlecode.cqengine.query.option.QueryOptions;
import com.googlecode.cqengine.resultset.ResultSet;
import com.googlecode.cqengine.resultset.filter.QuantizedResultSet;
import com.googlecode.cqengine.resultset.stored.StoredResultSet;
import com.googlecode.cqengine.resultset.stored.StoredSetBasedResultSet;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* An index backed by a {@link java.util.concurrent.ConcurrentHashMap} which indexes {@link CompoundAttribute}s,
* storing {@link CompoundValueTuple} objects as keys.
*
* Supports query types:
*
* -
* {@link com.googlecode.cqengine.index.compound.support.CompoundQuery}
*
*
* The constructor of this index accepts {@link Factory} objects, from which it will create the map and value sets it
* uses internally. This allows the application to "tune" the construction parameters of these maps/sets,
* by supplying custom factories.
* For default settings, supply {@link DefaultIndexMapFactory} and {@link DefaultValueSetFactory}.
*
* @author Niall Gallagher
*/
public class CompoundIndex extends AbstractMapBasedAttributeIndex, O, ConcurrentMap, StoredResultSet>> implements KeyStatisticsAttributeIndex, O> {
protected static final int INDEX_RETRIEVAL_COST = 20;
protected final CompoundAttribute attribute;
/**
* Package-private constructor, used by static factory methods. Creates a new HashIndex initialized to index the
* supplied attribute.
*
* @param indexMapFactory A factory used to create the main map-based data structure used by the index
* @param valueSetFactory A factory used to create sets to store values in the index
* @param attribute The attribute on which the index will be built
*/
protected CompoundIndex(Factory, StoredResultSet>> indexMapFactory, Factory> valueSetFactory, CompoundAttribute attribute) {
// We can supply the superclass constructor with an empty set of supported queries,
// because we implement/override supportsQuery() in this class instead...
super(indexMapFactory, valueSetFactory, attribute, Collections.>emptySet());
this.attribute = attribute;
}
/**
* Returns true if the given {@link Query} is based on the same list of attributes as the
* {@link CompoundAttribute} on which this compound index is based.
*
* @param query A {@link Query} to test
* @return True if the given {@link Query} is based on the same list of attributes as the
* {@link CompoundAttribute} on which this compound index is based, otherwise false
*/
@Override
public boolean supportsQuery(Query query) {
if (query instanceof CompoundQuery) {
CompoundQuery compoundQuery = (CompoundQuery) query;
return attribute.equals(compoundQuery.getCompoundAttribute());
}
return false;
}
@Override
public CompoundAttribute getAttribute() {
return attribute;
}
/**
* {@inheritDoc}
*
* This index is mutable.
*
* @return true
*/
@Override
public boolean isMutable() {
return true;
}
/**
* {@inheritDoc}
*/
@Override
public ResultSet retrieve(Query query, final QueryOptions queryOptions) {
Class> queryClass = query.getClass();
if (queryClass.equals(CompoundQuery.class)) {
final CompoundQuery compoundQuery = (CompoundQuery) query;
final CompoundValueTuple valueTuple = compoundQuery.getCompoundValueTuple();
return new ResultSet() {
@Override
public Iterator iterator() {
ResultSet rs = indexMap.get(getQuantizedValue(valueTuple));
return rs == null ? Collections.emptySet().iterator() : filterForQuantization(rs, compoundQuery, queryOptions).iterator();
}
@Override
public boolean contains(O object) {
ResultSet rs = indexMap.get(getQuantizedValue(valueTuple));
return rs != null && filterForQuantization(rs, compoundQuery, queryOptions).contains(object);
}
@Override
public int size() {
ResultSet rs = indexMap.get(getQuantizedValue(valueTuple));
return rs == null ? 0 : filterForQuantization(rs, compoundQuery, queryOptions).size();
}
@Override
public int getRetrievalCost() {
return INDEX_RETRIEVAL_COST;
}
@Override
public int getMergeCost() {
// Return size of entire stored set as merge cost...
ResultSet rs = indexMap.get(getQuantizedValue(valueTuple));
return rs == null ? 0 : rs.size();
}
@Override
public void close() {
// No op.
}
};
}
else {
throw new IllegalArgumentException("Unsupported query: " + query);
}
}
@Override
public CloseableIterable> getDistinctKeys(QueryOptions queryOptions) {
return super.getDistinctKeys();
}
@Override
public Integer getCountForKey(CompoundValueTuple key, QueryOptions queryOptions) {
return super.getCountForKey(key);
}
// ---------- Hook methods which can be overridden by subclasses using a Quantizer ----------
/**
* A no-op method which can be overridden by a subclass to return a {@link ResultSet} which filters objects from the
* given {@link ResultSet}, to return only those objects matching the query, for the case that the index is using a
* {@link com.googlecode.cqengine.quantizer.Quantizer}.
*
* This default implementation simply returns the given {@link ResultSet} unmodified.
*
* @param storedResultSet A {@link com.googlecode.cqengine.resultset.ResultSet} stored against a quantized key in the index
* @param query The query against which results should be matched
* @param queryOptions Optional parameters for the query
* @return A {@link ResultSet} which filters objects from the given {@link ResultSet},
* to return only those objects matching the query
*/
protected ResultSet filterForQuantization(ResultSet storedResultSet, Query query, QueryOptions queryOptions) {
return storedResultSet;
}
/**
* Creates a new {@link CompoundIndex} on the given combination of attributes.
*
* @param attributes The combination of simple attributes on which index will be built
* @param The type of the object containing the attributes
* @return A {@link CompoundIndex} based on these attributes
*/
// TODO: add overloaded non-varargs versions of this method to prevent unchecked warnings pre JDK 7?
public static CompoundIndex onAttributes(Attribute... attributes) {
return onAttributes(new DefaultIndexMapFactory(), new DefaultValueSetFactory(), attributes);
}
/**
* Creates a new {@link CompoundIndex} on the given combination of attributes.
*
* @param indexMapFactory A factory used to create the main map-based data structure used by the index
* @param valueSetFactory A factory used to create sets to store values in the index
* @param attributes The combination of simple attributes on which index will be built
* @param The type of the object containing the attributes
* @return A {@link CompoundIndex} based on these attributes
*/
// TODO: add overloaded non-varargs versions of this method to prevent unchecked warnings pre JDK 7?
public static CompoundIndex onAttributes(Factory, StoredResultSet>> indexMapFactory, Factory> valueSetFactory, Attribute... attributes) {
List> attributeList = Arrays.asList(attributes);
CompoundAttribute compoundAttribute = new CompoundAttribute(attributeList);
return new CompoundIndex(indexMapFactory, valueSetFactory, compoundAttribute);
}
/**
* Creates a new {@link CompoundIndex} using the given {@link Quantizer} on the given combination of attributes.
*
* @param attributes The combination of simple attributes on which index will be built
* @param quantizer A {@link Quantizer} to use in this index
* @param The type of the object containing the attributes
* @return A {@link CompoundIndex} based on these attributes
*/
public static CompoundIndex withQuantizerOnAttributes(final Quantizer> quantizer, Attribute... attributes) {
return withQuantizerOnAttributes(new DefaultIndexMapFactory(), new DefaultValueSetFactory(), quantizer, attributes);
}
/**
* Creates a new {@link CompoundIndex} using the given {@link Quantizer} on the given combination of attributes.
*
* @param indexMapFactory A factory used to create the main map-based data structure used by the index
* @param valueSetFactory A factory used to create sets to store values in the index
* @param attributes The combination of simple attributes on which index will be built
* @param quantizer A {@link Quantizer} to use in this index
* @param The type of the object containing the attributes
* @return A {@link CompoundIndex} based on these attributes
*/
public static CompoundIndex withQuantizerOnAttributes(Factory, StoredResultSet>> indexMapFactory, Factory> valueSetFactory, final Quantizer> quantizer, Attribute... attributes) {
List> attributeList = Arrays.asList(attributes);
CompoundAttribute compoundAttribute = new CompoundAttribute(attributeList);
return new CompoundIndex(indexMapFactory, valueSetFactory, compoundAttribute) {
// ---------- Override the hook methods related to Quantizer ----------
@Override
protected ResultSet filterForQuantization(ResultSet resultSet, final Query query, QueryOptions queryOptions) {
return new QuantizedResultSet(resultSet, query, queryOptions);
}
@Override
protected CompoundValueTuple getQuantizedValue(CompoundValueTuple attributeValue) {
return quantizer.getQuantizedValue(attributeValue);
}
@Override
public boolean isIndexQuantized() {
return true;
}
};
}
/**
* Creates an index map using default settings.
*/
public static class DefaultIndexMapFactory implements Factory, StoredResultSet>> {
@Override
public ConcurrentMap, StoredResultSet> create() {
return new ConcurrentHashMap, StoredResultSet>();
}
}
/**
* Creates a value set using default settings.
*/
public static class DefaultValueSetFactory implements Factory> {
@Override
public StoredResultSet create() {
return new StoredSetBasedResultSet(Collections.newSetFromMap(new ConcurrentHashMap()));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy