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}