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