public PartitionSearchResult computeResult()

in xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/DefaultSearchEngine.java [118:295]


    public PartitionSearchResult computeResult( PartitionTxn partitionTxn, SchemaManager schemaManager, 
        SearchOperationContext searchContext ) throws LdapException
    {
        SearchScope scope = searchContext.getScope();
        Dn baseDn = searchContext.getDn();
        AliasDerefMode aliasDerefMode = searchContext.getAliasDerefMode();
        ExprNode filter = searchContext.getFilter();

        // Compute the UUID of the baseDN entry
        String baseId = db.getEntryId( partitionTxn, baseDn );

        // Prepare the instance containing the search result
        PartitionSearchResult searchResult = new PartitionSearchResult( schemaManager );
        Set<IndexEntry<String, String>> resultSet = new HashSet<>();

        // Check that we have an entry, otherwise we can immediately get out
        if ( baseId == null )
        {
            if ( ( ( Partition ) db ).getSuffixDn().equals( baseDn ) )
            {
                // The context entry is not created yet, return an empty result
                searchResult.setResultSet( resultSet );

                return searchResult;
            }
            else
            {
                // The search base doesn't exist
                throw new LdapNoSuchObjectException( I18n.err( I18n.ERR_49029_INVALID_SEARCH_BASE, baseDn ) );
            }
        }

        // --------------------------------------------------------------------
        // Determine the effective base with aliases
        // --------------------------------------------------------------------
        Dn aliasedBase = null;


        if ( db.getAliasCache() != null )
        {
            aliasedBase = db.getAliasCache().getIfPresent( baseId );
        }
        else
        {
            aliasedBase = db.getAliasIndex().reverseLookup( partitionTxn, baseId );
        }

        Dn effectiveBase = baseDn;
        String effectiveBaseId = baseId;

        if ( ( aliasedBase != null ) && aliasDerefMode.isDerefFindingBase() )
        {
            /*
             * If the base is an alias and alias dereferencing does occur on
             * finding the base, or always then we set the effective base to the alias target
             * got from the alias index.
             */
            if ( !aliasedBase.isSchemaAware() )
            {
                effectiveBase = new Dn( schemaManager, aliasedBase );
            }
            else
            {
                effectiveBase = aliasedBase;
            }
            
            effectiveBaseId = db.getEntryId( partitionTxn, effectiveBase );
        }

        // --------------------------------------------------------------------
        // Specifically Handle Object Level Scope
        // --------------------------------------------------------------------
        if ( scope == SearchScope.OBJECT )
        {
            IndexEntry<String, String> indexEntry = new IndexEntry<>();
            indexEntry.setId( effectiveBaseId );

            // Fetch the entry, as we have only one
            Entry entry = db.fetch( partitionTxn, indexEntry.getId(), effectiveBase );

            Evaluator<? extends ExprNode> evaluator;

            if ( filter instanceof ObjectClassNode )
            {
                ScopeNode node = new ScopeNode( aliasDerefMode, effectiveBase, effectiveBaseId, scope );
                evaluator = new BaseLevelScopeEvaluator<>( db, node );
            }
            else
            {
                optimizer.annotate( partitionTxn, filter );
                evaluator = evaluatorBuilder.build( partitionTxn, filter );

                // Special case if the filter selects no candidate
                if ( evaluator == null )
                {
                    ScopeNode node = new ScopeNode( aliasDerefMode, effectiveBase, effectiveBaseId, scope );
                    evaluator = new BaseLevelScopeEvaluator<>( db, node );
                }
            }

            indexEntry.setEntry( entry );
            resultSet.add( indexEntry );

            searchResult.setEvaluator( evaluator );
            searchResult.setResultSet( resultSet );

            return searchResult;
        }

        // This is not a BaseObject scope search.

        // Add the scope node using the effective base to the filter
        ExprNode root;

        if ( filter instanceof ObjectClassNode )
        {
            root = new ScopeNode( aliasDerefMode, effectiveBase, effectiveBaseId, scope );
        }
        else
        {
            root = new AndNode();
            ( ( AndNode ) root ).getChildren().add( filter );
            ExprNode node = new ScopeNode( aliasDerefMode, effectiveBase, effectiveBaseId, scope );
            ( ( AndNode ) root ).getChildren().add( node );
        }

        // Annotate the node with the optimizer and return search enumeration.
        optimizer.annotate( partitionTxn, root );
        Evaluator<? extends ExprNode> evaluator = evaluatorBuilder.build( partitionTxn, root );

        Set<String> uuidSet = new HashSet<>();
        searchResult.setAliasDerefMode( aliasDerefMode );
        searchResult.setCandidateSet( uuidSet );

        long nbResults = cursorBuilder.build( partitionTxn, root, searchResult );

        LOG.debug( "Nb results : {} for filter : {}", nbResults, root );

        if ( nbResults < Long.MAX_VALUE )
        {
            for ( String uuid : uuidSet )
            {
                IndexEntry<String, String> indexEntry = new IndexEntry<>();
                indexEntry.setId( uuid );
                resultSet.add( indexEntry );
            }
        }
        else
        {
            // Full scan : use the MasterTable
            Cursor<IndexEntry<String, String>> cursor = new IndexCursorAdaptor( partitionTxn, db.getMasterTable().cursor(), true );

            try
            {
                while ( cursor.next() )
                {
                    IndexEntry<String, String> indexEntry = cursor.get();
    
                    // Here, the indexEntry contains a <UUID, Entry> tuple. Convert it to <UUID, UUID>
                    IndexEntry<String, String> forwardIndexEntry = new IndexEntry<>();
                    forwardIndexEntry.setKey( indexEntry.getKey() );
                    forwardIndexEntry.setId( indexEntry.getKey() );
                    forwardIndexEntry.setEntry( null );
    
                    resultSet.add( forwardIndexEntry );
                }
            }
            catch ( CursorException ce )
            {
                throw new LdapOtherException( ce.getMessage(), ce );
            }
        }

        searchResult.setEvaluator( evaluator );
        searchResult.setResultSet( resultSet );

        return searchResult;
    }