/*
* Copyright © 2014 Cask Data, 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 co.cask.cdap.explore.client;
import co.cask.cdap.api.data.format.FormatSpecification;
import co.cask.cdap.api.dataset.lib.PartitionKey;
import co.cask.cdap.explore.service.ExploreException;
import co.cask.cdap.explore.service.MetaDataInfo;
import co.cask.cdap.proto.ColumnDesc;
import co.cask.cdap.proto.Id;
import co.cask.cdap.proto.QueryResult;
import co.cask.cdap.proto.QueryStatus;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.AbstractIdleService;
import com.google.common.util.concurrent.ForwardingListenableFuture;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
/**
* Mock Explore client to use in test cases.
*/
public class MockExploreClient extends AbstractIdleService implements ExploreClient {
private final Map<String, List<ColumnDesc>> statementsToMetadata;
private final Map<String, List<QueryResult>> statementsToResults;
public MockExploreClient(Map<String, List<ColumnDesc>> statementsToMetadata,
Map<String, List<QueryResult>> statementsToResults) {
this.statementsToMetadata = Maps.newHashMap(statementsToMetadata);
this.statementsToResults = Maps.newHashMap(statementsToResults);
}
public MockExploreClient() {
this(ImmutableMap.<String, List<ColumnDesc>>of(), ImmutableMap.<String, List<QueryResult>>of());
}
@Override
public boolean isServiceAvailable() {
return true;
}
@Override
public ListenableFuture<Void> enableExploreDataset(Id.DatasetInstance datasetInstance) {
return null;
}
@Override
public ListenableFuture<Void> disableExploreDataset(Id.DatasetInstance datasetInstance) {
return null;
}
@Override
public ListenableFuture<Void> enableExploreStream(Id.Stream stream, String tableName, FormatSpecification format) {
return null;
}
@Override
public ListenableFuture<Void> disableExploreStream(Id.Stream stream, String tableName) {
return null;
}
@Override
public ListenableFuture<Void> addPartition(Id.DatasetInstance datasetInstance, PartitionKey key, String path) {
return null;
}
@Override
public ListenableFuture<Void> dropPartition(Id.DatasetInstance datasetInstance, PartitionKey key) {
return null;
}
@Override
public ListenableFuture<ExploreExecutionResult> submit(Id.Namespace namespace, final String statement) {
SettableFuture<ExploreExecutionResult> futureDelegate = SettableFuture.create();
futureDelegate.set(new MockExploreExecutionResult(statementsToResults.get(statement).iterator(),
statementsToMetadata.get(statement)));
return new MockStatementExecutionFuture(futureDelegate, statement, statementsToMetadata, statementsToResults);
}
@Override
public ListenableFuture<ExploreExecutionResult> columns(@Nullable String catalog, @Nullable String schemaPattern,
String tableNamePattern, String columnNamePattern) {
SettableFuture<ExploreExecutionResult> futureDelegate = SettableFuture.create();
futureDelegate.set(new MockExploreExecutionResult(statementsToResults.get("columns_stmt").iterator(),
statementsToMetadata.get("columns_stmt")));
return new MockStatementExecutionFuture(futureDelegate, "columns_stmt", statementsToMetadata, statementsToResults);
}
@Override
public ListenableFuture<ExploreExecutionResult> catalogs() {
SettableFuture<ExploreExecutionResult> futureDelegate = SettableFuture.create();
futureDelegate.set(new MockExploreExecutionResult(statementsToResults.get("catalogs_stmt").iterator(),
statementsToMetadata.get("catalogs_stmt")));
return new MockStatementExecutionFuture(futureDelegate, "catalogs_stmt", statementsToMetadata, statementsToResults);
}
@Override
public ListenableFuture<ExploreExecutionResult> schemas(@Nullable String catalog, @Nullable String schemaPattern) {
SettableFuture<ExploreExecutionResult> futureDelegate = SettableFuture.create();
futureDelegate.set(new MockExploreExecutionResult(statementsToResults.get("schemas_stmt").iterator(),
statementsToMetadata.get("schemas_stmt")));
return new MockStatementExecutionFuture(futureDelegate, "schemas_stmt",
statementsToMetadata, statementsToResults);
}
@Override
public ListenableFuture<ExploreExecutionResult> functions(@Nullable String catalog, @Nullable String schemaPattern,
String functionNamePattern) {
SettableFuture<ExploreExecutionResult> futureDelegate = SettableFuture.create();
futureDelegate.set(new MockExploreExecutionResult(statementsToResults.get("functions_stmt").iterator(),
statementsToMetadata.get("functions_stmt")));
return new MockStatementExecutionFuture(futureDelegate, "functions_stmt",
statementsToMetadata, statementsToResults);
}
@Override
public ListenableFuture<MetaDataInfo> info(MetaDataInfo.InfoType infoType) {
return null;
}
@Override
public ListenableFuture<ExploreExecutionResult> tables(@Nullable String catalog, @Nullable String schemaPattern,
String tableNamePattern, @Nullable List<String> tableTypes) {
SettableFuture<ExploreExecutionResult> futureDelegate = SettableFuture.create();
futureDelegate.set(new MockExploreExecutionResult(statementsToResults.get("tables_stmt").iterator(),
statementsToMetadata.get("tables_stmt")));
return new MockStatementExecutionFuture(futureDelegate, "tables_stmt",
statementsToMetadata, statementsToResults);
}
@Override
public ListenableFuture<ExploreExecutionResult> tableTypes() {
SettableFuture<ExploreExecutionResult> futureDelegate = SettableFuture.create();
futureDelegate.set(new MockExploreExecutionResult(statementsToResults.get("tableTypes_stmt").iterator(),
statementsToMetadata.get("tableTypes_stmt")));
return new MockStatementExecutionFuture(futureDelegate, "tableTypes_stmt",
statementsToMetadata, statementsToResults);
}
@Override
public ListenableFuture<ExploreExecutionResult> dataTypes() {
SettableFuture<ExploreExecutionResult> futureDelegate = SettableFuture.create();
futureDelegate.set(new MockExploreExecutionResult(statementsToResults.get("dataTypes_stmt").iterator(),
statementsToMetadata.get("dataTypes_stmt")));
return new MockStatementExecutionFuture(futureDelegate, "dataTypes_stmt",
statementsToMetadata, statementsToResults);
}
@Override
public ListenableFuture<ExploreExecutionResult> addNamespace(Id.Namespace namespace) {
return null;
}
@Override
public ListenableFuture<ExploreExecutionResult> removeNamespace(Id.Namespace namespace) {
return null;
}
@Override
protected void startUp() throws Exception {
// Do nothing
}
@Override
protected void shutDown() throws Exception {
// Do nothing
}
@Override
public void close() throws IOException {
// Do nothing
}
private static final class MockExploreExecutionResult implements ExploreExecutionResult {
private final Iterator<QueryResult> delegate;
private final List<ColumnDesc> schema;
MockExploreExecutionResult(Iterator<QueryResult> delegate, List<ColumnDesc> schema) {
this.delegate = delegate;
this.schema = schema;
}
@Override
public boolean hasNext() {
return delegate.hasNext();
}
@Override
public QueryResult next() {
return delegate.next();
}
@Override
public void remove() {
delegate.remove();
}
@Override
public void close() throws IOException {
// TODO should close the query here
}
@Override
public int getFetchSize() {
return 100;
}
@Override
public void setFetchSize(int fetchSize) {
// Do nothing
}
@Override
public List<ColumnDesc> getResultSchema() throws ExploreException {
return schema;
}
@Override
public boolean canContainResults() {
return true;
}
@Override
public QueryStatus getStatus() {
return QueryStatus.NO_OP;
}
}
private static final class MockStatementExecutionFuture
extends ForwardingListenableFuture.SimpleForwardingListenableFuture<ExploreExecutionResult>
implements ListenableFuture<ExploreExecutionResult> {
private final Map<String, List<ColumnDesc>> statementsToMetadata;
private final Map<String, List<QueryResult>> statementsToResults;
private final String statement;
MockStatementExecutionFuture(ListenableFuture<ExploreExecutionResult> delegate, String statement,
Map<String, List<ColumnDesc>> statementsToMetadata,
Map<String, List<QueryResult>> statementsToResults) {
super(delegate);
this.statement = statement;
this.statementsToMetadata = statementsToMetadata;
this.statementsToResults = statementsToResults;
}
@Override
public boolean cancel(boolean interrupt) {
statementsToMetadata.remove(statement);
statementsToResults.remove(statement);
return true;
}
}
}