class FilterAction extends Action<Query> {

    @Override
    public QueryResponse execute(Query parameter) throws QueryStoreException {
        parameter.setTable(ElasticsearchUtils.getValidTableName(parameter.getTable()));
        if (null == parameter.getFilters() || parameter.getFilters().isEmpty()) {
            parameter.setFilters(Lists.<Filter>newArrayList(new AnyFilter(parameter.getTable())));
        }
        if (null == parameter.getSort()) {
            ResultSort resultSort = new ResultSort();
            resultSort.setField("_timestamp");
            resultSort.setOrder(ResultSort.Order.desc);
            parameter.setSort(resultSort);
        }
        SearchRequestBuilder search = null;
        SearchResponse response;
        try {
            /*if(!tableManager.exists(query.getTable())) {
                throw new QueryStoreException(QueryStoreException.ErrorCode.NO_SUCH_TABLE,
                        "There is no table called: " + query.getTable());
            }*/
            search = getConnection().getClient().prepareSearch(ElasticsearchUtils.getIndices(parameter.getTable(), parameter))
                    .setTypes(ElasticsearchUtils.TYPE_NAME)
                    .setQuery(new ElasticSearchQueryGenerator(FilterCombinerType.and).genFilter(parameter.getFilters()))
                    .setSearchType(SearchType.QUERY_THEN_FETCH)
                    .setFrom(parameter.getFrom())
                    .setSize(parameter.getLimit());
            search.addSort(parameter.getSort().getField(),
                    ResultSort.Order.desc == parameter.getSort().getOrder() ? SortOrder.DESC : SortOrder.ASC);
            response = search.execute().actionGet();
            Vector<String> ids = new Vector<String>();
            for (SearchHit searchHit : response.getHits()) {
                ids.add(searchHit.getId());
            }
            if (ids.isEmpty()) {
                return new QueryResponse(Collections.<Document>emptyList());
            }
            return new QueryResponse(getQueryStore().get(parameter.getTable(), ids));
        } catch (Exception e) {
            if (null != search) {
                logger.error("Error running generated query: " + search, e);
            } else {
                logger.error("Query generation error: ", e);
            }
            throw new QueryStoreException(QueryStoreException.ErrorCode.QUERY_EXECUTION_ERROR,
                    "Error running query: " + parameter.toString());
        }
    }

}

class FilterActionTest {

    private QueryExecutor queryExecutor;
    private ObjectMapper mapper;
    private MockElasticsearchServer elasticsearchServer;
    private HazelcastInstance hazelcastInstance;

    @Test
    public void testQueryEmptyResult() throws QueryStoreException, JsonProcessingException {

        Query query = new Query();
        query.setTable(TestUtils.TEST_TABLE_NAME);

        EqualsFilter equalsFilter = new EqualsFilter();
        equalsFilter.setField("os");
        equalsFilter.setValue("wp8");
        query.setFilters(Lists.<Filter>newArrayList(equalsFilter));

        List<Document> documents = new ArrayList<Document>();
        QueryResponse actualResponse = QueryResponse.class.cast(queryExecutor.execute(query));
        compare(documents, actualResponse.getDocuments());
    }

}