org.apereo.portal.rest.search.PortletsSearchStrategy.java Source code

Java tutorial

Introduction

Here is the source code for org.apereo.portal.rest.search.PortletsSearchStrategy.java

Source

/**
 * Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information regarding copyright ownership. Apereo
 * licenses this file to you 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 the
 * following location:
 *
 * <p>http://www.apache.org/licenses/LICENSE-2.0
 *
 * <p>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.apereo.portal.rest.search;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apereo.portal.index.SearchField;
import org.apereo.portal.portlet.om.IPortletDefinition;
import org.apereo.portal.portlet.registry.IPortletDefinitionRegistry;
import org.apereo.portal.portlets.search.PortletRegistryUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * Provides search results to the {@link SearchRESTController} that are portlets.
 *
 * @since 5.0
 */
@Component
public class PortletsSearchStrategy implements ISearchStrategy {

    private static final String RESULT_TYPE_NAME = "portlets";

    private MultiFieldQueryParser queryParser;

    @Autowired
    private Directory directory;

    @Autowired
    private IPortletDefinitionRegistry portletDefinitionRegistry;

    @Autowired
    private PortletRegistryUtil portletRegistryUtil;

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @PostConstruct
    public void init() {
        final String[] fields = Arrays.stream(SearchField.values()).map(SearchField::getValue)
                .toArray(String[]::new);
        queryParser = new MultiFieldQueryParser(fields, new StandardAnalyzer());
    }

    @Override
    public String getResultTypeName() {
        return RESULT_TYPE_NAME;
    }

    @Override
    public List<?> search(String query, HttpServletRequest request) {

        final List<Object> rslt = new ArrayList<>();
        final Set<IPortletDefinition> seen = new HashSet<>();

        try (IndexReader indexReader = DirectoryReader.open(directory)) {

            final Query q = queryParser.parse(query);
            final IndexSearcher searcher = new IndexSearcher(indexReader);
            final TopDocs topDocs = searcher.search(q, 50);
            Arrays.stream(topDocs.scoreDocs).forEach(scoreDoc -> {
                try {
                    final Document document = searcher.doc(scoreDoc.doc);
                    final IPortletDefinition portlet = portletDefinitionRegistry
                            .getPortletDefinitionByFname(document.get(SearchField.FNAME.getValue()));
                    if (seen.contains(portlet)) {
                        // Don't process a portlet more than once...
                        return;
                    }
                    seen.add(portlet);
                    logger.debug("Search query '{}' matches portlet: {}", query, portlet);
                    /* requester permissions checked in buildPortletUrl() */
                    final String url = portletRegistryUtil.buildPortletUrl(request, portlet);
                    if (url != null) {
                        logger.debug("Adding portlet with fname='{}' to search results for query='{}'",
                                portlet.getFName(), query);
                        rslt.add(getPortletAttrs(portlet, url));
                    }
                } catch (IOException e) {
                    // Log a warning, but don't prevent other matches from
                    // succeeding...
                    logger.warn("Failed to process the following search result for query='{}': {}", query, scoreDoc,
                            e);
                }
            });

        } catch (Exception e) {
            // Log a warning, but don't prevent other search strategies from succeeding...
            logger.warn("Failed to search portal content for query='{}'", query, e);
        }

        return rslt;
    }

    private Map<String, String> getPortletAttrs(IPortletDefinition portlet, String url) {
        final Map<String, String> rslt = new TreeMap<>();
        rslt.put("name", portlet.getName());
        rslt.put("fname", portlet.getFName());
        rslt.put("title", portlet.getTitle());
        rslt.put("description", portlet.getDescription());
        rslt.put("url", url);
        return rslt;
    }
}