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}