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", PageContext.REQUEST_SCOPE );
082            setList( searchresults );
083            
084            int skip = 0;
085            
086            //  Skip the first few ones...
087            m_iterator = searchresults.iterator();
088            while( m_iterator.hasNext() && (skip++ < m_start) ) m_iterator.next();
089        }
090
091        m_count = 0;
092        m_wikiContext = (WikiContext) pageContext.getAttribute( WikiTagBase.ATTR_CONTEXT, PageContext.REQUEST_SCOPE );
093
094        return nextResult();
095    }
096
097    private int nextResult()
098    {
099        if( m_iterator != null && m_iterator.hasNext() && m_count++ < m_maxItems )
100        {
101            SearchResult r = (SearchResult) m_iterator.next();
102            
103            // Create a wiki context for the result
104            WikiEngine engine = m_wikiContext.getEngine();
105            HttpServletRequest request = m_wikiContext.getHttpRequest();
106            Command command = PageCommand.VIEW.targetedCommand( r.getPage() );
107            WikiContext context = new WikiContext( engine, request, command );
108            
109            // Stash it in the page context
110            pageContext.setAttribute( WikiTagBase.ATTR_CONTEXT,
111                                      context,
112                                      PageContext.REQUEST_SCOPE );
113            pageContext.setAttribute( getId(), r );
114
115            return EVAL_BODY_BUFFERED;
116        }
117
118        return SKIP_BODY;
119    }
120
121    public int doAfterBody()
122    {
123        if( bodyContent != null )
124        {
125            try
126            {
127                JspWriter out = getPreviousOut();
128                out.print(bodyContent.getString());
129                bodyContent.clearBody();
130            }
131            catch( IOException e )
132            {
133                log.error("Unable to get inner tag text", e);
134                // FIXME: throw something?
135            }
136        }
137
138        return nextResult();
139    }
140
141    public int doEndTag()
142    {
143        m_iterator = null;
144
145        return super.doEndTag();
146    }
147}