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