Package org.eurekastreams.server.search.stream

Source Code of org.eurekastreams.server.search.stream.ActivityIdSearchPageFetcher

/*
* Copyright (c) 2009-2010 Lockheed Martin Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.eurekastreams.server.search.stream;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.search.Sort;
import org.eurekastreams.commons.search.ProjectionSearchRequestBuilder;
import org.hibernate.search.jpa.FullTextQuery;

/**
* PageFetcher to return a list of Activity IDs for a Lucene search query.
*/
public class ActivityIdSearchPageFetcher implements PageFetcher<Long>
{
    /**
     * The logger.
     */
    private Log log = LogFactory.getLog(ActivityIdSearchPageFetcher.class);

    /**
     * A multiplier of page size to use when the user is fetching a subsequent page of data - ask for more results than
     * we need so we minimize calls to search.
     */
    private static Long pageSizeMultiplierForSubsequentPages;

    /**
     * The Lucene search query.
     */
    private String searchQuery;

    /**
     * The search request builder.
     */
    private ProjectionSearchRequestBuilder searchRequestBuilder;

    /**
     * The last Activity ID that the user saw - fetch results after that point.
     */
    private Long lastSeenActivityId;

    /**
     * Constructor - taking the Lucene search query and the ProjectionSearchRequestBuilder.
     *
     * @param inSearchQuery
     *            the native Lucene search query
     * @param inSearchRequestBuilder
     *            the ProjectionSearchRequestBuilder to use to execute the query
     * @param inLastSeenActivityId
     *            the last activity id that the user saw - results should have ids less than this
     * @param inPageSizeMultiplierForSubsequentPages
     *            the multiplier to use against the requested page size when the user is looking for search results past
     *            page 1.
     */
    public ActivityIdSearchPageFetcher(final String inSearchQuery,
            final ProjectionSearchRequestBuilder inSearchRequestBuilder, final Long inLastSeenActivityId,
            final Long inPageSizeMultiplierForSubsequentPages)
    {
        searchQuery = inSearchQuery;
        searchRequestBuilder = inSearchRequestBuilder;
        lastSeenActivityId = inLastSeenActivityId;
        pageSizeMultiplierForSubsequentPages = inPageSizeMultiplierForSubsequentPages;

        if (lastSeenActivityId == null || lastSeenActivityId <= 0)
        {
            lastSeenActivityId = Long.MAX_VALUE;
        }
    }

    /**
     * Fetch a page of activity IDs.
     *
     * @param inStartIndex
     *            the starting index of the page to fetch - not used
     * @param inPageSize
     *            the page size
     * @return a list of Activity IDs
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<Long> fetchPage(final int inStartIndex, final int inPageSize)
    {
        int pageSize = inPageSize;
        if (lastSeenActivityId != Long.MAX_VALUE)
        {
            // If no new activities were added since the user saw the previous
            // page, we'd want to fetch [startIndex, startIndex+inPageSize).
            // We'll fetch a little bit more in case there were extra activities
            // thrown on top.
            pageSize *= pageSizeMultiplierForSubsequentPages;
        }

        FullTextQuery query = searchRequestBuilder.buildQueryFromNativeSearchString(searchQuery);
        query.setSort(new Sort("id", true));
        List<Long> results = new ArrayList<Long>();
        int totalResults = 0;
        int batchSize = 0;
        do
        {
            // get the page size results - don't trust the previous offset in
            // case new activities were added on top
            if (log.isTraceEnabled())
            {
                log.trace("Preparing a query - search: '" + searchQuery + "'; paging:[0," + (pageSize - 1) + "]");
            }

            searchRequestBuilder.setPaging(query, 0, pageSize - 1);

            List<Long> queryResults = query.getResultList();
            if (totalResults == 0)
            {
                // only need to fetch this once - it describes the total results
                // regardless of paging
                totalResults = query.getResultSize();
            }
            batchSize = queryResults.size();

            if (log.isTraceEnabled())
            {
                log.trace("Found: " + batchSize + " of " + totalResults + " results.");
            }

            for (Long activityId : queryResults)
            {
                if (results.size() >= inPageSize)
                {
                    // all done
                    break;
                }
                if (activityId < lastSeenActivityId)
                {
                    if (log.isTraceEnabled())
                    {
                        log.trace("Found activity id: " + activityId + ", which is lower than " + lastSeenActivityId
                                + ", adding to the result list");
                    }
                    // remember this id in case we have to get a second page of
                    // results, to avoid adding it twice
                    lastSeenActivityId = activityId;
                    results.add(activityId);
                }
            }

            // get another page next round
            pageSize += pageSize;
        }
        while (
        // we haven't filled the page yet
        results.size() < inPageSize
        // we got back less results than we asked for - must not be any
                // more
                && batchSize < totalResults);

        // the search request builder should be configured to only fetch ids, so
        // we'll have to populate the rest from
        // the database
        return results;
    }
}
TOP

Related Classes of org.eurekastreams.server.search.stream.ActivityIdSearchPageFetcher

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.