blob: 6d47060b6f4c3770e1298e6106fab4e8416f2f56 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.rya.indexing.entity;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import org.apache.hadoop.conf.Configurable;
import org.apache.hadoop.conf.Configuration;
import org.apache.log4j.Logger;
import org.apache.rya.indexing.entity.model.Entity;
import org.apache.rya.indexing.entity.query.EntityQueryNode;
import org.apache.rya.indexing.entity.storage.EntityStorage;
import org.apache.rya.indexing.entity.storage.EntityStorage.EntityStorageException;
import org.apache.rya.indexing.entity.storage.TypeStorage;
import org.apache.rya.indexing.entity.update.mongo.MongoEntityIndexer;
import org.apache.rya.indexing.external.matching.AbstractExternalSetOptimizer;
import org.apache.rya.indexing.external.matching.ExternalSetMatcher;
import org.apache.rya.indexing.external.matching.ExternalSetProvider;
import org.apache.rya.indexing.external.matching.QueryNodeListRater;
import org.apache.rya.indexing.external.matching.QuerySegment;
import org.apache.rya.indexing.external.matching.TopOfQueryFilterRelocator;
import org.apache.rya.mongodb.StatefulMongoDBRdfConfiguration;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.Dataset;
import org.eclipse.rdf4j.query.algebra.TupleExpr;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
/**
* Optimizes a query over {@link Entity}s.
*/
public class EntityIndexOptimizer extends AbstractExternalSetOptimizer<EntityQueryNode> implements Configurable {
private static final Logger log = Logger.getLogger(EntityIndexOptimizer.class);
private static final EntityExternalSetMatcherFactory MATCHER_FACTORY = new EntityExternalSetMatcherFactory();
private final MongoEntityIndexer indexer;
private EntityIndexSetProvider provider;
private Configuration conf;
private EntityStorage entityStorage;
private TypeStorage typeStorage;
/**
* Creates a new {@link EntityIndexOptimizer}.
*/
public EntityIndexOptimizer() {
indexer = new MongoEntityIndexer();
//There is no rater for entity query nodes.
useOptimal = false;
}
@Override
public void setConf(final Configuration conf) {
checkState(conf instanceof StatefulMongoDBRdfConfiguration,
"The provided Configuration must be of type StatefulMongoDBRdfConfiguration, but was " + conf.getClass().getName());
this.conf = conf;
indexer.setConf(conf);
indexer.init();
typeStorage = indexer.getTypeStorage();
try {
entityStorage = indexer.getEntityStorage();
} catch (final EntityStorageException e) {
log.error("Error getting entity storage", e);
}
provider = new EntityIndexSetProvider(typeStorage, entityStorage);
}
@Override
public Configuration getConf() {
return conf;
}
@Override
public void optimize(TupleExpr tupleExpr, final Dataset dataset, final BindingSet bindings) {
checkNotNull(tupleExpr);
checkNotNull(indexer);
// first standardize query by pulling all filters to top of query if
// they exist using TopOfQueryFilterRelocator
tupleExpr = TopOfQueryFilterRelocator.moveFiltersToTop(tupleExpr);
super.optimize(tupleExpr, null, null);
}
@VisibleForTesting
public EntityStorage getEntityStorage() {
return entityStorage;
}
@VisibleForTesting
public TypeStorage getTypeStorage() {
return typeStorage;
}
/**
* Visits a node of the query tree. Checks to see if the node belongs
* or is of an {@link Entity}. If it is, prepares it, so after the query
* is checked, the nodes can be replaced with {@link EntityQueryNode}s.
*/
@Override
protected ExternalSetMatcher<EntityQueryNode> getMatcher(final QuerySegment<EntityQueryNode> segment) {
return MATCHER_FACTORY.getMatcher(segment);
}
@Override
protected ExternalSetProvider<EntityQueryNode> getProvider() {
return provider;
}
@Override
protected Optional<QueryNodeListRater> getNodeListRater(final QuerySegment<EntityQueryNode> segment) {
return Optional.absent();
}
}