public static SolrReaderSetScorer createReaderSetScorer(
      Weight weight,
      AtomicReaderContext context,
      Bits acceptDocs,
      SolrIndexSearcher searcher,
      String authorities,
      AtomicReader reader)
      throws IOException {

    DocSet readableDocSet =
        (DocSet) searcher.cacheLookup(CacheConstants.ALFRESCO_READER_CACHE, authorities);

    if (readableDocSet == null) {

      String[] auths = authorities.substring(1).split(authorities.substring(0, 1));

      readableDocSet = new BitDocSet(new FixedBitSet(searcher.maxDoc()));

      BooleanQuery bQuery = new BooleanQuery();
      for (String current : auths) {
        bQuery.add(new TermQuery(new Term(QueryConstants.FIELD_READER, current)), Occur.SHOULD);
      }

      DocSet aclDocs = searcher.getDocSet(bQuery);

      BooleanQuery aQuery = new BooleanQuery();
      for (DocIterator it = aclDocs.iterator(); it.hasNext(); /**/ ) {
        int docID = it.nextDoc();
        // Obtain the ACL ID for this ACL doc.
        long aclID =
            searcher.getAtomicReader().getNumericDocValues(QueryConstants.FIELD_ACLID).get(docID);
        SchemaField schemaField = searcher.getSchema().getField(QueryConstants.FIELD_ACLID);
        Query query = schemaField.getType().getFieldQuery(null, schemaField, Long.toString(aclID));
        aQuery.add(query, Occur.SHOULD);

        if ((aQuery.clauses().size() > 999) || !it.hasNext()) {
          DocSet docsForAclId = searcher.getDocSet(aQuery);
          readableDocSet = readableDocSet.union(docsForAclId);

          aQuery = new BooleanQuery();
        }
      }
      // Exclude the ACL docs from the results, we only want real docs that match.
      // Probably not very efficient, what we really want is remove(docID)
      readableDocSet = readableDocSet.andNot(aclDocs);
      searcher.cacheInsert(CacheConstants.ALFRESCO_READER_CACHE, authorities, readableDocSet);
    }

    // TODO: cache the full set? e.g. searcher.cacheInsert(CacheConstants.ALFRESCO_READERSET_CACHE,
    // authorities, readableDocSet)
    // plus check of course, for presence in cache at start of method.
    return new SolrReaderSetScorer(weight, readableDocSet, context, acceptDocs, searcher);
  }
  public static SolrCachingAuxDocScorer createAuxDocScorer(
      SolrIndexSearcher searcher, Similarity similarity, Query query, SolrIndexReader reader)
      throws IOException {
    // Get hold of solr top level searcher
    // Execute query with caching
    // translate reults to leaf docs
    // build ordered doc list

    DocSet auxDocSet = searcher.getDocSet(query);

    CacheEntry[] indexedByDocId =
        (CacheEntry[])
            searcher.cacheLookup(
                AlfrescoSolrEventListener.ALFRESCO_CACHE,
                AlfrescoSolrEventListener.KEY_DBID_LEAF_PATH_BY_DOC_ID);

    // List<ScoreDoc> auxDocs = pathCollector.getDocs();
    OpenBitSet translated = new OpenBitSet();

    if (auxDocSet instanceof BitDocSet) {
      BitDocSet source = (BitDocSet) auxDocSet;
      OpenBitSet openBitSet = source.getBits();
      int current = -1;
      while ((current = openBitSet.nextSetBit(current + 1)) != -1) {
        CacheEntry entry = indexedByDocId[current];
        translated.set(entry.getLeaf());
      }
    } else {
      for (DocIterator it = auxDocSet.iterator(); it.hasNext(); /* */ ) {
        CacheEntry entry = indexedByDocId[it.nextDoc()];
        translated.set(entry.getLeaf());
      }
    }

    return new SolrCachingAuxDocScorer(similarity, new BitDocSet(translated), reader);
  }
  public static SolrAuthoritySetScorer createAuthoritySetScorer(
      SolrIndexSearcher searcher, Similarity similarity, String authorities, SolrIndexReader reader)
      throws IOException {
    // Get hold of solr top level searcher
    // Execute query with caching
    // translate reults to leaf docs
    // build ordered doc list

    Properties p = searcher.getSchema().getResourceLoader().getCoreProperties();
    boolean doPermissionChecks =
        Boolean.parseBoolean(p.getProperty("alfresco.doPermissionChecks", "true"));

    Query key = new SolrAuthoritySetQuery(authorities);

    DocSet answer =
        (DocSet) searcher.cacheLookup(AlfrescoSolrEventListener.ALFRESCO_AUTHORITY_CACHE, key);
    if (answer != null) {
      return new SolrAuthoritySetScorer(similarity, answer, reader);
    }

    HashSet<String> globalReaders =
        (HashSet<String>)
            searcher.cacheLookup(
                AlfrescoSolrEventListener.ALFRESCO_CACHE,
                AlfrescoSolrEventListener.KEY_GLOBAL_READERS);

    String[] auths = authorities.substring(1).split(authorities.substring(0, 1));

    boolean hasGlobalRead = false;

    for (String auth : auths) {
      if (globalReaders.contains(auth)) {
        hasGlobalRead = true;
        break;
      }
    }

    if (hasGlobalRead || (doPermissionChecks == false)) {
      // can read all
      OpenBitSet allLeafDocs =
          (OpenBitSet)
              searcher.cacheLookup(
                  AlfrescoSolrEventListener.ALFRESCO_CACHE,
                  AlfrescoSolrEventListener.KEY_ALL_LEAF_DOCS);
      return new SolrAuthoritySetScorer(similarity, new BitDocSet(allLeafDocs), reader);
    }

    DocSet readableDocSet = searcher.getDocSet(new SolrReaderSetQuery(authorities));

    if (globalReaders.contains(PermissionService.OWNER_AUTHORITY)) {
      DocSet authorityOwnedDocs = searcher.getDocSet(new SolrOwnerSetQuery(authorities));

      DocSet toCache = readableDocSet.union(authorityOwnedDocs);
      searcher.cacheInsert(AlfrescoSolrEventListener.ALFRESCO_AUTHORITY_CACHE, key, toCache);
      return new SolrAuthoritySetScorer(similarity, toCache, reader);
    } else {
      // for that docs I own that have owner Read rights
      DocSet ownerReadableDocSet =
          searcher.getDocSet(new SolrReaderSetQuery("|" + PermissionService.OWNER_AUTHORITY));
      DocSet authorityOwnedDocs = searcher.getDocSet(new SolrOwnerSetQuery(authorities));

      DocSet docsAuthorityOwnsAndCanRead = ownerReadableDocSet.intersection(authorityOwnedDocs);

      DocSet toCache = readableDocSet.union(docsAuthorityOwnsAndCanRead);
      searcher.cacheInsert(AlfrescoSolrEventListener.ALFRESCO_AUTHORITY_CACHE, key, toCache);
      return new SolrAuthoritySetScorer(similarity, toCache, reader);
    }
  }