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.tags;
020
021import java.io.IOException;
022import java.util.Collection;
023
024import javax.servlet.http.HttpServletRequest;
025import javax.servlet.jsp.JspWriter;
026import javax.servlet.jsp.PageContext;
027
028import org.apache.log4j.Logger;
029import org.apache.wiki.WikiContext;
030import org.apache.wiki.WikiEngine;
031import org.apache.wiki.search.SearchResult;
032import org.apache.wiki.ui.Command;
033import org.apache.wiki.ui.PageCommand;
034
035/**
036 *  Iterates through Search result results.
037 *
038 *  <P><B>Attributes</B></P>
039 *  <UL>
040 *    <LI>max = how many search results should be shown.
041 *  </UL>
042 *
043 *  @since 2.0
044 */
045
046// FIXME: Shares MUCH too much in common with IteratorTag.  Must refactor.
047public class SearchResultIteratorTag
048    extends IteratorTag
049{
050    private static final long serialVersionUID = 0L;
051    
052    private   int         m_maxItems;
053    private   int         m_count = 0;
054    private   int         m_start = 0;
055    
056    private static final Logger log = Logger.getLogger(SearchResultIteratorTag.class);
057    
058    public void release()
059    {
060        super.release();
061        m_maxItems = m_count = 0;
062    }
063
064    public void setMaxItems( int arg )
065    {
066        m_maxItems = arg;
067    }
068
069    public void setStart( int arg )
070    {
071        m_start = arg;
072    }
073    
074    public final int doStartTag()
075    {
076        //
077        //  Do lazy eval if the search results have not been set.
078        //
079        if( m_iterator == null )
080        {
081            Collection searchresults = (Collection) pageContext.getAttribute( "searchresults",
082                                                                              PageContext.REQUEST_SCOPE );
083            setList( searchresults );
084            
085            int skip = 0;
086            
087            //  Skip the first few ones...
088            m_iterator = searchresults.iterator();
089            while( m_iterator.hasNext() && (skip++ < m_start) ) m_iterator.next();
090        }
091
092        m_count       = 0;
093        m_wikiContext = (WikiContext) pageContext.getAttribute( WikiTagBase.ATTR_CONTEXT,
094                                                                PageContext.REQUEST_SCOPE );
095
096        return nextResult();
097    }
098
099    private int nextResult()
100    {
101        if( m_iterator != null && m_iterator.hasNext() && m_count++ < m_maxItems )
102        {
103            SearchResult r = (SearchResult) m_iterator.next();
104            
105            // Create a wiki context for the result
106            WikiEngine engine = m_wikiContext.getEngine();
107            HttpServletRequest request = m_wikiContext.getHttpRequest();
108            Command command = PageCommand.VIEW.targetedCommand( r.getPage() );
109            WikiContext context = new WikiContext( engine, request, command );
110            
111            // Stash it in the page context
112            pageContext.setAttribute( WikiTagBase.ATTR_CONTEXT,
113                                      context,
114                                      PageContext.REQUEST_SCOPE );
115            pageContext.setAttribute( getId(), r );
116
117            return EVAL_BODY_BUFFERED;
118        }
119
120        return SKIP_BODY;
121    }
122
123    public int doAfterBody()
124    {
125        if( bodyContent != null )
126        {
127            try
128            {
129                JspWriter out = getPreviousOut();
130                out.print(bodyContent.getString());
131                bodyContent.clearBody();
132            }
133            catch( IOException e )
134            {
135                log.error("Unable to get inner tag text", e);
136                // FIXME: throw something?
137            }
138        }
139
140        return nextResult();
141    }
142
143    public int doEndTag()
144    {
145        m_iterator = null;
146
147        return super.doEndTag();
148    }
149}