    001/*
    002    Licensed to the Apache Software Foundation (ASF) under one
    003    or more contributor license agreements.  See the NOTICE file
    004    distributed with this work for additional information
    005    regarding copyright ownership.  The ASF licenses this file
    006    to you under the Apache License, Version 2.0 (the
    007    "License"); you may not use this file except in compliance
    008    with the License.  You may obtain a copy of the License at
    009
    010       http://www.apache.org/licenses/LICENSE-2.0
    011
    012    Unless required by applicable law or agreed to in writing,
    013    software distributed under the License is distributed on an
    014    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015    KIND, either express or implied.  See the License for the
    016    specific language governing permissions and limitations
    017    under the License.
    018*/
    019package org.apache.wiki.plugin;
    020
    021import org.apache.logging.log4j.LogManager;
    022import org.apache.logging.log4j.Logger;
    023import org.apache.wiki.api.core.Context;
    024import org.apache.wiki.api.core.ContextEnum;
    025import org.apache.wiki.api.core.Engine;
    026import org.apache.wiki.api.exceptions.PluginException;
    027import org.apache.wiki.api.exceptions.ProviderException;
    028import org.apache.wiki.api.plugin.Plugin;
    029import org.apache.wiki.api.search.SearchResult;
    030import org.apache.wiki.render.RenderingManager;
    031import org.apache.wiki.search.SearchManager;
    032import org.apache.wiki.util.TextUtil;
    033import org.apache.wiki.util.XHTML;
    034import org.apache.wiki.util.XhtmlUtil;
    035import org.jdom2.Element;
    036
    037import java.io.IOException;
    038import java.util.Collection;
    039import java.util.Iterator;
    040import java.util.Map;
    041
    042/**
    043 *  The "Search" plugin allows you to access the JSPWiki search routines and show the displays in an array on your page.
    044 *
    045 *  <p>Parameters : </p>
    046 *  <ul>
    047 *  <li><b>query</b> - String. A standard JSPWiki search query.</li>
    048 *  <li><b>set</b> - String. The JSPWiki context variable that will hold the results of the query. This allows you to pass your queries to other plugins on the same page as well. </li>
    049 *  <li><b>max</b> - Integer. How many search results are shown at maximum.</li>
    050 *  </ul>
    051 *
    052 *  @since
    053 */
    054public class Search implements Plugin {
    055
    056    private static final Logger LOG = LogManager.getLogger(Search.class);
    057
    058    /** Parameter name for setting the query string.  Value is <tt>{@value}</tt>. */
    059    public static final String PARAM_QUERY = "query";
    060
    061    /** Parameter name for setting the name of the set where the results are stored. Value is <tt>{@value}</tt>. */
    062    public static final String PARAM_SET   = "set";
    063
    064    /** The default name of the result set. */
    065    public static final String DEFAULT_SETNAME = "_defaultSet";
    066
    067    /** The parameter name for setting the how many results will be fetched. Value is <tt>{@value}</tt>. */
    068    public static final String PARAM_MAX   = "max";
    069
    070    /**
    071     * {@inheritDoc}
    072     */
    073    @Override
    074    public String execute( final Context context, final Map<String, String> params ) throws PluginException {
    075        int maxItems = Integer.MAX_VALUE;
    076        final Collection< SearchResult > results;
    077
    078        final String queryString = params.get( PARAM_QUERY );
    079        String set               = params.get( PARAM_SET );
    080        final String max         = params.get( PARAM_MAX );
    081
    082        if ( set == null ) set = DEFAULT_SETNAME;
    083        if ( max != null ) maxItems = Integer.parseInt( max );
    084
    085        if ( queryString == null ) {
    086            results = context.getVariable( set );
    087        } else {
    088            try {
    089                results = doBasicQuery( context, queryString );
    090                context.setVariable( set, results );
    091            } catch( final Exception e ) {
    092                return "<div class='error'>" + TextUtil.replaceEntities(e.getMessage()) + "</div>\n";
    093            }
    094        }
    095
    096        String res = "";
    097
    098        if ( results != null ) {
    099            res = renderResults(results,context,maxItems);
    100        }
    101
    102        return res;
    103    }
    104
    105    private Collection<SearchResult> doBasicQuery( final Context context, final String query ) throws ProviderException, IOException {
    106        LOG.debug( "Searching for string " + query );
    107        return context.getEngine().getManager( SearchManager.class ).findPages( query, context );
    108    }
    109
    110    private String renderResults( final Collection<SearchResult> results, final Context context, final int maxItems ) {
    111        final Engine engine = context.getEngine();
    112
    113        final Element table = XhtmlUtil.element(XHTML.table);
    114        //table.setAttribute(XHTML.ATTR_border,"0");
    115        //table.setAttribute(XHTML.ATTR_cellpadding,"4");
    116        table.setAttribute(XHTML.ATTR_class,"wikitable search-result");
    117
    118        Element row = XhtmlUtil.element(XHTML.tr);
    119        table.addContent(row);
    120
    121        final Element th1 = XhtmlUtil.element(XHTML.th,"Page");
    122        th1.setAttribute(XHTML.ATTR_width,"30%");
    123        th1.setAttribute(XHTML.ATTR_align,"left");
    124        row.addContent(th1);
    125
    126        final Element th2 = XhtmlUtil.element(XHTML.th,"Score");
    127        th2.setAttribute(XHTML.ATTR_align,"left");
    128        row.addContent(th2);
    129
    130        int idx = 0;
    131        for ( final Iterator<SearchResult> i = results.iterator(); i.hasNext() && idx++ <= maxItems; ) {
    132            final SearchResult sr = i.next();
    133            row = XhtmlUtil.element(XHTML.tr);
    134
    135            final Element name = XhtmlUtil.element(XHTML.td);
    136            name.setAttribute(XHTML.ATTR_width,"30%");
    137
    138            name.addContent( XhtmlUtil.link(context.getURL( ContextEnum.PAGE_VIEW.getRequestContext(), sr.getPage().getName() ),
    139                             engine.getManager( RenderingManager.class ).beautifyTitle(sr.getPage().getName() ) ) );
    140
    141            row.addContent(name);
    142
    143            row.addContent(XhtmlUtil.element(XHTML.td,""+sr.getScore()));
    144
    145            table.addContent(row);
    146        }
    147
    148        if ( results.isEmpty() ) {
    149            row = XhtmlUtil.element(XHTML.tr);
    150
    151            final Element td = XhtmlUtil.element(XHTML.td);
    152            td.setAttribute(XHTML.ATTR_colspan,"2");
    153            final Element b = XhtmlUtil.element(XHTML.b,"No results");
    154            td.addContent(b);
    155
    156            row.addContent(td);
    157
    158            table.addContent(row);
    159        }
    160
    161        return XhtmlUtil.serialize(table);
    162    }
    163}