package org.jboss.capedwarf.datastore.query; import java.util.ArrayList; import java.util.List; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.Projection; import com.google.appengine.api.datastore.Query; import org.apache.lucene.search.Sort; import org.infinispan.query.CacheQuery; import org.infinispan.query.SearchManager; import org.jboss.capedwarf.shared.config.IndexesXml; /** * Converts a GAE query to Infinispan's CacheQuery * * @author <a href="mailto:marko.luksa@gmail.com">Marko Luksa</a> */ public class QueryConverter { public static final String KIND_PROPERTY_KEY = "____capedwarf.entity.kind___"; public static final String NAMESPACE_PROPERTY_KEY = "____capedwarf.entity.namespace___"; public static final String ANCESTOR_PROPERTY_KEY = "____capedwarf.entity.ancestor.key___"; private LuceneQueryBuilder queryBuilder; private SearchManager searchManager; private FilterConverter filterConverter; private SortPredicateConverter sortPredicateConverter; public QueryConverter(SearchManager searchManager) { this.searchManager = searchManager; this.queryBuilder = new LuceneQueryBuilder(searchManager.buildQueryBuilderForClass(Entity.class).get()); this.filterConverter = new FilterConverter(queryBuilder); this.sortPredicateConverter = new SortPredicateConverter(); } public CacheQuery convert(Query gaeQuery, IndexesXml.Index index) { CacheQuery cacheQuery = getCacheQuery(createLuceneQuery(gaeQuery)); Projections.applyProjections(gaeQuery, cacheQuery, index); addSortToQuery(cacheQuery, gaeQuery); return cacheQuery; } private void addSortToQuery(CacheQuery cacheQuery, Query gaeQuery) { List<Query.SortPredicate> sortPredicates = gaeQuery.getSortPredicates(); if (!sortPredicates.isEmpty()) { Sort sort = sortPredicateConverter.convert(sortPredicates); cacheQuery.sort(sort); } } private CacheQuery getCacheQuery(org.apache.lucene.search.Query luceneQuery) { return searchManager.getQuery(luceneQuery, Entity.class); } private org.apache.lucene.search.Query createLuceneQuery(Query gaeQuery) { return queryBuilder.all(getQueryList(gaeQuery)); } private List<org.apache.lucene.search.Query> getQueryList(Query gaeQuery) { List<org.apache.lucene.search.Query> list = new ArrayList<org.apache.lucene.search.Query>(); addFilterQuery(list, gaeQuery); addNamespaceQuery(list, QueryUtils.getNamespace(gaeQuery)); addEntityKindQuery(list, gaeQuery.getKind()); addAncestorQuery(list, gaeQuery.getAncestor()); addProjectionsFilterQuery(list, gaeQuery); return list; } private void addProjectionsFilterQuery(List<org.apache.lucene.search.Query> list, Query gaeQuery) { for (Projection projection : gaeQuery.getProjections()) { list.add(queryBuilder.notEqual(projection.getName(), Bridge.NullBridge.NULL_TOKEN)); } } private void addFilterQuery(List<org.apache.lucene.search.Query> list, Query gaeQuery) { Query.Filter filter = getFilter(gaeQuery); list.add(filterConverter.convert(filter)); } private Query.Filter getFilter(Query gaeQuery) { List<Query.Filter> filters = getAllFilterPredicates(gaeQuery); if (filters.size() == 1) { return filters.get(0); } else if (filters.size() > 1) { return Query.CompositeFilterOperator.and(filters); } else { return null; } } @SuppressWarnings("deprecation") private List<Query.Filter> getAllFilterPredicates(Query gaeQuery) { List<Query.Filter> list = new ArrayList<Query.Filter>(); if (gaeQuery.getFilter() != null) { list.add(gaeQuery.getFilter()); } list.addAll(gaeQuery.getFilterPredicates()); return list; } private void addAncestorQuery(List<org.apache.lucene.search.Query> list, Key ancestor) { if (ancestor != null) { list.add(equal(ANCESTOR_PROPERTY_KEY, Bridge.KEY.objectToString(ancestor))); } } private void addEntityKindQuery(List<org.apache.lucene.search.Query> list, String kind) { if (kind != null) { list.add(equal(KIND_PROPERTY_KEY, kind)); } } private void addNamespaceQuery(List<org.apache.lucene.search.Query> list, String namespace) { if (namespace != null) { list.add(equal(NAMESPACE_PROPERTY_KEY, NamespaceBridge.objectToString(namespace))); } } public org.apache.lucene.search.Query equal(String fieldName, String value) { return queryBuilder.equal(fieldName, value); } }