code: public QueryExecutor<S> executor(Filter<S> filter, OrderingList<S> ordering, QueryHints hints)
          throws RepositoryException
      {
          final Key<S> key = new Key<S>(filter, ordering, hints);
  
          synchronized (mPrimaryCache) {
              QueryExecutor<S> executor = mPrimaryCache.get(key);
              if (executor != null) {
                  return executor;
              }
          }
  
          // Fallback to second level cache, which may still have the executor because
          // garbage collection has not reclaimed it yet. It also allows some concurrent
          // executor creation, by using filter-specific locks.
  
          SoftValuedCache<Object, QueryExecutor<S>> cache;
          synchronized (mFilterToExecutor) {
              cache = mFilterToExecutor.get(filter);
              if (cache == null) {
                  cache = SoftValuedCache.newCache(7);
                  mFilterToExecutor.put(filter, cache);
              }
          }
  
          Object subKey;
          if (hints == null || hints.isEmpty()) {
              subKey = ordering;
          } else {
              // Don't construct key with filter. It is not needed here and it would prevent
              // garbage collection of filters.
              subKey = new Key(null, ordering, hints);
          }
  
          QueryExecutor<S> executor;
          synchronized (cache) {
              executor = cache.get(subKey);
              if (executor == null) {
                  executor = mFactory.executor(filter, ordering, hints);
                  cache.put(subKey, executor);
              }
          }
  
          synchronized (mPrimaryCache) {
              mPrimaryCache.put(key, executor);
          }
  
          return executor;
      }
docs: Returns an executor from the cache.
  
  @param filter optional filter
  @param ordering optional order-by properties
  @param hints optional query hints