    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.Locale;
    041import java.util.Map;
    042import java.util.ResourceBundle;
    043
    044/**
    045 *  The "Search" plugin allows you to access the JSPWiki search routines and show the displays in an array on your page.
    046 *
    047 *  <p>Parameters : </p>
    048 *  <ul>
    049 *  <li><b>query</b> - String. A standard JSPWiki search query.</li>
    050 *  <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>
    051 *  <li><b>max</b> - Integer. How many search results are shown at maximum.</li>
    052 *  </ul>
    053 *
    054 *  @since
    055 */
    056public class Search implements Plugin {
    057
    058    private static final Logger LOG = LogManager.getLogger(Search.class);
    059
    060    /** Parameter name for setting the query string.  Value is <tt>{@value}</tt>. */
    061    public static final String PARAM_QUERY = "query";
    062
    063    /** Parameter name for setting the name of the set where the results are stored. Value is <tt>{@value}</tt>. */
    064    public static final String PARAM_SET   = "set";
    065
    066    /** The default name of the result set. */
    067    public static final String DEFAULT_SETNAME = "_defaultSet";
    068
    069    /** The parameter name for setting the how many results will be fetched. Value is <tt>{@value}</tt>. */
    070    public static final String PARAM_MAX   = "max";
    071
    072    @Override
    073    public String getDisplayName(Locale locale) {
    074        final ResourceBundle rb = ResourceBundle.getBundle(PluginManager.PLUGIN_I18N_RESOURCE, locale);
    075        return rb.getString(this.getClass().getSimpleName());
    076    }
    077
    078    @Override
    079    public String getSnipExample() {
    080        return "Search query='{Janne}' max='10'";
    081    }
    082
    083
    084    /**
    085     * {@inheritDoc}
    086     */
    087    @Override
    088    public String execute( final Context context, final Map<String, String> params ) throws PluginException {
    089        int maxItems = Integer.MAX_VALUE;
    090        final Collection< SearchResult > results;
    091
    092        final String queryString = params.get( PARAM_QUERY );
    093        String set               = params.get( PARAM_SET );
    094        final String max         = params.get( PARAM_MAX );
    095
    096        if ( set == null ) set = DEFAULT_SETNAME;
    097        if ( max != null ) maxItems = Integer.parseInt( max );
    098
    099        if ( queryString == null ) {
    100            results = context.getVariable( set );
    101        } else {
    102            try {
    103                results = doBasicQuery( context, queryString );
    104                context.setVariable( set, results );
    105            } catch( final Exception e ) {
    106                return "<div class='error'>" + TextUtil.replaceEntities(e.getMessage()) + "</div>\n";
    107            }
    108        }
    109
    110        String res = "";
    111
    112        if ( results != null ) {
    113            res = renderResults(results,context,maxItems);
    114        }
    115
    116        return res;
    117    }
    118
    119    private Collection<SearchResult> doBasicQuery( final Context context, final String query ) throws ProviderException, IOException {
    120        LOG.debug( "Searching for string " + query );
    121        return context.getEngine().getManager( SearchManager.class ).findPages( query, context );
    122    }
    123
    124    private String renderResults( final Collection<SearchResult> results, final Context context, final int maxItems ) {
    125        final Engine engine = context.getEngine();
    126
    127        final Element table = XhtmlUtil.element(XHTML.table);
    128        //table.setAttribute(XHTML.ATTR_border,"0");
    129        //table.setAttribute(XHTML.ATTR_cellpadding,"4");
    130        table.setAttribute(XHTML.ATTR_class,"wikitable search-result");
    131
    132        Element row = XhtmlUtil.element(XHTML.tr);
    133        table.addContent(row);
    134
    135        final Element th1 = XhtmlUtil.element(XHTML.th,"Page");
    136        th1.setAttribute(XHTML.ATTR_width,"30%");
    137        th1.setAttribute(XHTML.ATTR_align,"left");
    138        row.addContent(th1);
    139
    140        final Element th2 = XhtmlUtil.element(XHTML.th,"Score");
    141        th2.setAttribute(XHTML.ATTR_align,"left");
    142        row.addContent(th2);
    143
    144        int idx = 0;
    145        for ( final Iterator<SearchResult> i = results.iterator(); i.hasNext() && idx++ <= maxItems; ) {
    146            final SearchResult sr = i.next();
    147            row = XhtmlUtil.element(XHTML.tr);
    148
    149            final Element name = XhtmlUtil.element(XHTML.td);
    150            name.setAttribute(XHTML.ATTR_width,"30%");
    151
    152            name.addContent( XhtmlUtil.link(context.getURL( ContextEnum.PAGE_VIEW.getRequestContext(), sr.getPage().getName() ),
    153                             engine.getManager( RenderingManager.class ).beautifyTitle(sr.getPage().getName() ) ) );
    154
    155            row.addContent(name);
    156
    157            row.addContent(XhtmlUtil.element(XHTML.td,""+sr.getScore()));
    158
    159            table.addContent(row);
    160        }
    161
    162        if ( results.isEmpty() ) {
    163            row = XhtmlUtil.element(XHTML.tr);
    164
    165            final Element td = XhtmlUtil.element(XHTML.td);
    166            td.setAttribute(XHTML.ATTR_colspan,"2");
    167            final Element b = XhtmlUtil.element(XHTML.b,"No results");
    168            td.addContent(b);
    169
    170            row.addContent(td);
    171
    172            table.addContent(row);
    173        }
    174
    175        return XhtmlUtil.serialize(table);
    176    }
    177}