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    */
019    package org.apache.wiki.plugin;
020    
021    import org.apache.log4j.Logger;
022    import org.apache.wiki.WikiContext;
023    import org.apache.wiki.WikiEngine;
024    import org.apache.wiki.api.exceptions.PluginException;
025    import org.apache.wiki.api.exceptions.ProviderException;
026    import org.apache.wiki.api.plugin.WikiPlugin;
027    import org.apache.wiki.search.SearchResult;
028    import org.apache.wiki.util.XHTML;
029    import org.apache.wiki.util.XhtmlUtil;
030    import org.jdom2.Element;
031    
032    import java.io.IOException;
033    import java.util.Collection;
034    import java.util.Iterator;
035    import java.util.Map;
036    
037    /**
038     *  The "Search" plugin allows you to access the JSPWiki search routines and show the displays in an array on your page. 
039     *  
040     *  <p>Parameters : </p>
041     *  <ul>
042     *  <li><b>query</b> - String. A standard JSPWiki search query.</li>
043     *  <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>
044     *  <li><b>max</b> - Integer. How many search results are shown at maximum.</li> 
045     *  </ul>
046     *  
047     *  @since 
048     */
049    public class Search implements WikiPlugin
050    {
051        static Logger log = Logger.getLogger(Search.class);
052        
053        /** Parameter name for setting the query string.  Value is <tt>{@value}</tt>. */
054        public static final String PARAM_QUERY = "query";
055    
056        /** Parameter name for setting the name of the set where the results are stored.  
057         *  Value is <tt>{@value}</tt>. 
058         */
059        public static final String PARAM_SET   = "set";
060        
061        /** The default name of the result set. */
062        public static final String DEFAULT_SETNAME = "_defaultSet";
063        
064        /** The parameter name for setting the how many results will be fetched.
065         *  Value is <tt>{@value}</tt>.
066         */
067        public static final String PARAM_MAX   = "max";
068        
069        /**
070         * {@inheritDoc}
071         */
072        @SuppressWarnings("unchecked")
073        public String execute( WikiContext context, Map<String, String> params ) throws PluginException
074        {
075            int maxItems = Integer.MAX_VALUE;
076            Collection<SearchResult> results = null;
077            
078            String queryString = params.get( PARAM_QUERY );
079            String set         = params.get( PARAM_SET );
080            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            {
087                results = (Collection<SearchResult>)context.getVariable( set );
088            }
089            else
090            {
091                try
092                {
093                    results = doBasicQuery( context, queryString );
094                    context.setVariable( set, results );
095                }
096                catch( Exception e )
097                {
098                    return "<div class='error'>"+e.getMessage()+"</div>\n";
099                }
100            }
101            
102            String res = "";
103            
104            if ( results != null )
105            {
106                res = renderResults(results,context,maxItems);
107            }
108            
109            return res;
110        }
111        
112        private Collection<SearchResult> doBasicQuery( WikiContext context, String query )
113            throws ProviderException, IOException
114        {
115            log.debug("Searching for string "+query);
116    
117            @SuppressWarnings("unchecked")
118            Collection<SearchResult> list = context.getEngine().findPages( query );
119    
120            return list;
121        }
122        
123        private String renderResults( Collection<SearchResult> results, WikiContext context, int maxItems )
124        {
125            WikiEngine engine = context.getEngine();
126            
127            Element table = XhtmlUtil.element(XHTML.table);
128            table.setAttribute(XHTML.ATTR_border,"0");
129            table.setAttribute(XHTML.ATTR_cellpadding,"4");
130            
131            Element row = XhtmlUtil.element(XHTML.tr);
132            table.addContent(row);
133            
134            Element th1 = XhtmlUtil.element(XHTML.th,"Page");
135            th1.setAttribute(XHTML.ATTR_width,"30%");
136            th1.setAttribute(XHTML.ATTR_align,"left");
137            row.addContent(th1);
138            
139            Element th2 = XhtmlUtil.element(XHTML.th,"Score");
140            th2.setAttribute(XHTML.ATTR_align,"left");
141            row.addContent(th2);
142            
143            int idx = 0;
144            for ( Iterator<SearchResult> i = results.iterator(); i.hasNext() && idx++ <= maxItems; )
145            {
146                SearchResult sr = i.next();
147                row = XhtmlUtil.element(XHTML.tr);
148    
149                Element name = XhtmlUtil.element(XHTML.td);
150                name.setAttribute(XHTML.ATTR_width,"30%");
151                
152                name.addContent( XhtmlUtil.link(context.getURL( WikiContext.VIEW, sr.getPage().getName()),
153                        engine.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            {
164                row = XhtmlUtil.element(XHTML.tr);
165                
166                Element td = XhtmlUtil.element(XHTML.td);
167                td.setAttribute(XHTML.ATTR_colspan,"2");
168                Element b = XhtmlUtil.element(XHTML.b,"No results");
169                td.addContent(b);
170                
171                row.addContent(td);
172    
173                table.addContent(row);
174            }
175            
176            return XhtmlUtil.serialize(table);
177        }
178    }