You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by sn...@apache.org on 2005/09/25 21:02:00 UTC

svn commit: r291460 - in /incubator/roller/branches/roller_2.0: src/org/roller/business/search/operations/ src/org/roller/presentation/search/ src/org/roller/presentation/velocity/ tests/org/roller/presentation/ web/WEB-INF/ web/WEB-INF/classes/ web/th...

Author: snoopdave
Date: Sun Sep 25 12:01:45 2005
New Revision: 291460

URL: http://svn.apache.org/viewcvs?rev=291460&view=rev
Log:
Fixing search, which was broken by 2.0

Added:
    incubator/roller/branches/roller_2.0/src/org/roller/presentation/search/
    incubator/roller/branches/roller_2.0/src/org/roller/presentation/search/SearchAction.java
    incubator/roller/branches/roller_2.0/src/org/roller/presentation/search/SearchResultsPageModel.java
    incubator/roller/branches/roller_2.0/src/org/roller/presentation/search/SearchServlet.java
    incubator/roller/branches/roller_2.0/web/theme/searchResults.jsp
Removed:
    incubator/roller/branches/roller_2.0/src/org/roller/presentation/velocity/SearchServlet.java
Modified:
    incubator/roller/branches/roller_2.0/src/org/roller/business/search/operations/RebuildWebsiteIndexOperation.java
    incubator/roller/branches/roller_2.0/tests/org/roller/presentation/SearchServletTest.java
    incubator/roller/branches/roller_2.0/web/WEB-INF/classes/ApplicationResources.properties
    incubator/roller/branches/roller_2.0/web/WEB-INF/classes/searchresults.vm
    incubator/roller/branches/roller_2.0/web/WEB-INF/classes/searchresults_day.vm
    incubator/roller/branches/roller_2.0/web/WEB-INF/classes/weblog.vm
    incubator/roller/branches/roller_2.0/web/WEB-INF/tiles-defs.xml
    incubator/roller/branches/roller_2.0/web/theme/search.jsp

Modified: incubator/roller/branches/roller_2.0/src/org/roller/business/search/operations/RebuildWebsiteIndexOperation.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/src/org/roller/business/search/operations/RebuildWebsiteIndexOperation.java?rev=291460&r1=291459&r2=291460&view=diff
==============================================================================
--- incubator/roller/branches/roller_2.0/src/org/roller/business/search/operations/RebuildWebsiteIndexOperation.java (original)
+++ incubator/roller/branches/roller_2.0/src/org/roller/business/search/operations/RebuildWebsiteIndexOperation.java Sun Sep 25 12:01:45 2005
@@ -71,8 +71,12 @@
         {
             if (reader != null)
             {
-                Term tWebsite = IndexUtil.getTerm(FieldConstants.WEBSITE_HANDLE, 
-                                   website.getHandle());
+                Term tWebsite = null;
+                if (website != null) 
+                {
+                    tWebsite = IndexUtil.getTerm(
+                        FieldConstants.WEBSITE_HANDLE, website.getHandle());
+                }
                 if (tWebsite != null)
                 {
                     reader.delete(tWebsite);

Added: incubator/roller/branches/roller_2.0/src/org/roller/presentation/search/SearchAction.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/src/org/roller/presentation/search/SearchAction.java?rev=291460&view=auto
==============================================================================
--- incubator/roller/branches/roller_2.0/src/org/roller/presentation/search/SearchAction.java (added)
+++ incubator/roller/branches/roller_2.0/src/org/roller/presentation/search/SearchAction.java Sun Sep 25 12:01:45 2005
@@ -0,0 +1,40 @@
+/*
+ * SearchAction.java
+ *
+ * Created on September 21, 2005, 11:36 AM
+ */
+package org.roller.presentation.search;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+import org.roller.config.RollerConfig;
+
+/**
+ * Executes site wide search.
+ * @author Dave Johnson
+ *
+ * @struts.action name="search" path="/sitesearch" scope="request"
+ * @struts.action-forward name="search.page" path=".search"
+ */
+public class SearchAction extends Action {
+    
+    public ActionForward execute(
+            ActionMapping mapping, ActionForm form,
+            HttpServletRequest request, HttpServletResponse response)
+            throws Exception {
+
+        String enabled = RollerConfig.getProperty("search.enabled");
+        if("false".equalsIgnoreCase(enabled)) {
+            return mapping.findForward("main");
+        }           
+        // search model executes search, makes results available to page
+        SearchResultsPageModel model = new SearchResultsPageModel(
+                "search.title", request, response, mapping);
+        request.setAttribute("searchResults", model);
+        return mapping.findForward("search.page");
+    }
+}

Added: incubator/roller/branches/roller_2.0/src/org/roller/presentation/search/SearchResultsPageModel.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/src/org/roller/presentation/search/SearchResultsPageModel.java?rev=291460&view=auto
==============================================================================
--- incubator/roller/branches/roller_2.0/src/org/roller/presentation/search/SearchResultsPageModel.java (added)
+++ incubator/roller/branches/roller_2.0/src/org/roller/presentation/search/SearchResultsPageModel.java Sun Sep 25 12:01:45 2005
@@ -0,0 +1,301 @@
+/*
+ * SearchResultsPageModel.java
+ *
+ * Created on September 23, 2005, 11:27 AM
+ */
+
+package org.roller.presentation.search;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.collections.comparators.ReverseComparator;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.search.Hits;
+import org.apache.struts.action.ActionMapping;
+import org.roller.RollerException;
+import org.roller.business.search.FieldConstants;
+import org.roller.business.search.operations.SearchOperation;
+import org.roller.model.IndexManager;
+import org.roller.model.Roller;
+import org.roller.model.RollerFactory;
+import org.roller.model.UserManager;
+import org.roller.model.WeblogManager;
+import org.roller.pojos.WeblogEntryComparator;
+import org.roller.pojos.WeblogEntryData;
+import org.roller.pojos.WebsiteData;
+import org.roller.presentation.BasePageModel;
+import org.roller.presentation.RollerRequest;
+import org.roller.util.DateUtil;
+import org.roller.util.StringUtils;
+
+/**
+ * Encapsulate seach result in page model so I can be used from Velocity or JSP.
+ * @author Min (original code)
+ * @author Dave Johnson (encapsulation)
+ */
+public class SearchResultsPageModel extends BasePageModel {
+    
+    private String   term = "";
+    private Integer  hits = new Integer(0);
+    private Integer  offset = new Integer(0);
+    private Integer  limit = new Integer(0);
+    private TreeMap  results = new TreeMap();
+    private Set      categories = new TreeSet();
+    private boolean  websiteSpecificSearch = false;
+    private String   errorMessage = null;
+    
+    /* How many results to display */
+    private static int LIMIT = 10;
+    
+    /* Where to start fetching results */
+    private static int OFFSET = 0;
+    
+    private static Log mLogger =
+        LogFactory.getFactory().getInstance(SearchResultsPageModel.class);
+    private static ResourceBundle bundle = 
+        ResourceBundle.getBundle("ApplicationResources");          
+
+    public SearchResultsPageModel(
+        String titleKey,
+        HttpServletRequest request,
+        HttpServletResponse response,
+        ActionMapping mapping) throws RollerException, IOException {
+        
+        super(titleKey, request, response, mapping);
+
+        setWebsiteSpecificSearch(checkForWebsite(request));
+        RollerRequest rreq = RollerRequest.getRollerRequest(request);
+        
+        SearchOperation search =
+            new SearchOperation(RollerFactory.getRoller().getIndexManager());
+        search.setTerm(request.getParameter("q"));
+        setTerm(request.getParameter("q"));
+
+        WebsiteData website = null;
+        if (isWebsiteSpecificSearch()) {
+            website = rreq.getWebsite();
+            search.setWebsiteHandle(rreq.getWebsite().getHandle());
+        }
+
+        if (StringUtils.isNotEmpty(request.getParameter("c"))) {
+            search.setCategory(request.getParameter("c"));
+        }
+
+        // execute search
+        executeSearch(RollerFactory.getRoller(), search);
+
+        if (search.getResultsCount() == -1) {
+            // this means there has been a parsing (or IO) error
+            setErrorMessage(bundle.getString("error.searchProblem"));
+        } else {
+            // Convert the Hits into WeblogEntryData instances.
+            Hits hits = search.getResults();
+            setResults(convertHitsToEntries(rreq, website, hits));
+            setOffset((Integer)request.getAttribute("offset"));
+            setLimit((Integer)request.getAttribute("limit"));
+            if (request.getAttribute("categories") != null) {
+                Set cats = (Set)request.getAttribute("categories");
+                if (cats.size() > 0) {
+                    setCategories(cats);
+                }
+            }
+        }
+        setHits(new Integer(search.getResultsCount()));
+    }
+    private void executeSearch(Roller roller, SearchOperation search)
+        throws RollerException {
+        IndexManager indexMgr = roller.getIndexManager();
+        indexMgr.executeIndexOperationNow(search);
+        if (mLogger.isDebugEnabled()) {
+            mLogger.debug("numresults = " + search.getResultsCount());
+        }
+    }
+    /** Look in PathInfo so req.getRemoteUser() doesn't interfere. */
+    private boolean checkForWebsite(HttpServletRequest request) {
+        if (StringUtils.isNotEmpty(
+                request.getParameter(RollerRequest.WEBLOG_KEY))) {
+            return true;
+        }        
+        String pathInfoStr = request.getPathInfo();
+        pathInfoStr = (pathInfoStr!=null) ? pathInfoStr : "";
+        
+        String[] pathInfo = StringUtils.split(pathInfoStr,"/");
+        if ( pathInfo.length > 0 ) {
+            return true; // is a user page
+        }
+        return false;
+    }
+   /**
+     * Iterate over Hits and build sets of WeblogEntryData
+     * objects, placed into Date buckets (in reverse order).
+     * @param rreq
+     * @param website
+     * @param hits
+     * @throws RollerException
+     * @throws IOException
+     */
+    private TreeMap convertHitsToEntries(
+            RollerRequest rreq, WebsiteData website, Hits hits)
+            throws RollerException, IOException {
+        // determine offset (starting point)
+        int ioffset = useOffset(rreq.getRequest());
+        if (ioffset >= hits.length()) ioffset = OFFSET;
+        rreq.getRequest().setAttribute("offset", new Integer(ioffset));
+        
+        // determine limit (number of results to display)
+        int ilimit = useLimit(rreq.getRequest());
+        rreq.getRequest().setAttribute("limit", new Integer(ilimit));
+        if (ioffset + ilimit > hits.length()) ilimit = hits.length()-ioffset;
+        
+        boolean websiteSpecificSearch = checkForWebsite(rreq.getRequest());
+        TreeMap searchResults = new TreeMap(new ReverseComparator());
+        TreeSet categories = new TreeSet();
+        Roller roller = RollerFactory.getRoller();
+        UserManager userMgr = roller.getUserManager();
+        WeblogManager weblogMgr =roller.getWeblogManager();
+        WeblogEntryData entry;
+        Document doc = null;
+        String handle = null;
+        for (int i = ioffset; i < ioffset+ilimit; i++) {
+            entry = null; // reset for each iteration
+            
+            doc = hits.doc(i);
+            handle = doc.getField(FieldConstants.WEBSITE_HANDLE).stringValue();
+            
+            if (websiteSpecificSearch && website != null) {
+                // "wrong user" results have been reported
+                if (handle.equals(rreq.getWebsite().getHandle())) {
+                    // get real entry for display on user's site
+                    entry = weblogMgr.retrieveWeblogEntry(
+                            doc.getField(FieldConstants.ID).stringValue() );
+                }
+            } else {
+                // if user is not enabled, website will be null
+                //entry = buildSearchEntry(website, doc);
+                entry = weblogMgr.retrieveWeblogEntry(
+                        doc.getField(FieldConstants.ID).stringValue() );
+                if (doc.getField(FieldConstants.CATEGORY) != null) {
+                    categories.add(
+                            doc.getField(FieldConstants.CATEGORY).stringValue());
+                }
+            }
+            
+            // maybe null if search result returned inactive user
+            // or entry's user is not the requested user.
+            if (entry != null) {
+                addToSearchResults(searchResults, entry);
+            }
+        }
+        rreq.getRequest().setAttribute("categories", categories);
+        return searchResults;
+    }
+    private void addToSearchResults(
+            TreeMap searchResults, WeblogEntryData entry) {
+        // convert entry's each date to midnight (00m 00h 00s)
+        Date midnight = DateUtil.getStartOfDay( entry.getPubTime() );
+        
+        // ensure we do not get duplicates from Lucene by
+        // using a Set Collection.  Entries sorted by pubTime.
+        TreeSet set = (TreeSet) searchResults.get(midnight);
+        if (set == null) {
+            // date is not mapped yet, so we need a new Set
+            set = new TreeSet( new WeblogEntryComparator() );
+            searchResults.put(midnight, set);
+        }
+        set.add(entry);
+    }
+    private int useOffset(HttpServletRequest request) {
+        int offset = OFFSET;
+        if (request.getParameter("o") != null) {
+            try {
+                offset = Integer.valueOf(request.getParameter("o")).intValue();
+            } catch (NumberFormatException e) {
+                // Not a valid Integer
+            }
+        }
+        return offset;
+    }
+    private int useLimit(HttpServletRequest request) {
+        int limit = LIMIT;
+        if (request.getParameter("n") != null) {
+            try {
+                limit = Integer.valueOf(request.getParameter("n")).intValue();
+            } catch (NumberFormatException e) {
+                // Not a valid Integer
+            }
+        }
+        return limit;
+    }
+
+    public String getTerm() {
+        return term;
+    }
+
+    public void setTerm(String term) {
+        this.term = term;
+    }
+
+    public Integer getHits() {
+        return hits;
+    }
+
+    public void setHits(Integer hits) {
+        this.hits = hits;
+    }
+
+    public Integer getOffset() {
+        return offset;
+    }
+
+    public void setOffset(Integer offset) {
+        this.offset = offset;
+    }
+
+    public Integer getLimit() {
+        return limit;
+    }
+
+    public void setLimit(Integer limit) {
+        this.limit = limit;
+    }
+
+    public TreeMap getResults() {
+        return results;
+    }
+
+    public void setResults(TreeMap results) {
+        this.results = results;
+    }
+
+    public Set getCategories() {
+        return categories;
+    }
+
+    public void setCategories(Set categories) {
+        this.categories = categories;
+    }
+
+    public boolean isWebsiteSpecificSearch() {
+        return websiteSpecificSearch;
+    }
+
+    public void setWebsiteSpecificSearch(boolean websiteSpecificSearch) {
+        this.websiteSpecificSearch = websiteSpecificSearch;
+    }
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    public void setErrorMessage(String errorMessage) {
+        this.errorMessage = errorMessage;
+    }
+}
\ No newline at end of file

Added: incubator/roller/branches/roller_2.0/src/org/roller/presentation/search/SearchServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/src/org/roller/presentation/search/SearchServlet.java?rev=291460&view=auto
==============================================================================
--- incubator/roller/branches/roller_2.0/src/org/roller/presentation/search/SearchServlet.java (added)
+++ incubator/roller/branches/roller_2.0/src/org/roller/presentation/search/SearchServlet.java Sun Sep 25 12:01:45 2005
@@ -0,0 +1,131 @@
+package org.roller.presentation.search;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.jsp.JspFactory;
+import javax.servlet.jsp.PageContext;
+
+import org.apache.commons.collections.comparators.ReverseComparator;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.search.Hits;
+import org.apache.struts.action.ActionMapping;
+import org.apache.velocity.Template;
+import org.apache.velocity.context.Context;
+import org.roller.RollerException;
+import org.roller.business.search.FieldConstants;
+import org.roller.business.search.operations.SearchOperation;
+import org.roller.config.RollerConfig;
+import org.roller.model.IndexManager;
+import org.roller.model.Roller;
+import org.roller.model.RollerFactory;
+import org.roller.model.UserManager;
+import org.roller.model.WeblogManager;
+import org.roller.pojos.WeblogEntryComparator;
+import org.roller.pojos.WeblogEntryData;
+import org.roller.pojos.WebsiteData;
+import org.roller.presentation.BasePageModel;
+import org.roller.presentation.RollerRequest;
+import org.roller.util.DateUtil;
+import org.roller.util.StringUtils;
+import org.roller.presentation.velocity.*;
+
+/**
+ * This servlet retrieves (and displays) search results.
+ *
+ * @web.servlet name="SearchServlet" load-on-startup="5"
+ * @web.servlet-init-param name="properties" value="/WEB-INF/velocity.properties"
+ * @web.servlet-mapping url-pattern="/search/*"
+ */
+public class SearchServlet extends BasePageServlet {
+    
+    static final long serialVersionUID = -2150090108300585670L;
+    
+    private static Log mLogger =
+            LogFactory.getFactory().getInstance(SearchServlet.class);
+    
+    private boolean searchEnabled = true;
+    
+    public Template handleRequest(HttpServletRequest request,
+        HttpServletResponse response, Context ctx) throws Exception {
+        
+        // Note: Removed request character encoding here; was too late; 
+        // it is now set uniformly in CharEncodingFilter. See ROL-760.
+        
+        String enabled = RollerConfig.getProperty("search.enabled");
+        if("false".equalsIgnoreCase(enabled))
+            this.searchEnabled = false;
+        
+        if(! this.searchEnabled) {
+            Template outty = null;
+            Exception pageException = null;
+            try {
+                ContextLoader.setupContext(
+                    ctx, RollerRequest.getRollerRequest(request), response );
+                outty = getTemplate( "searchdisabled.vm", "UTF-8" );
+            } catch (Exception e) {
+               pageException = e;
+               response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+            }
+            
+            if (pageException != null) {
+                mLogger.error("EXCEPTION: in RollerServlet", pageException);
+                request.setAttribute("DisplayException", pageException);
+            }
+            return outty;
+        }
+        
+        // do no work if query term is empty
+        if (StringUtils.isEmpty(request.getParameter("q"))) {
+            return generalSearchResults(request, response, ctx);
+        }
+        
+        // search model executes search, makes results available to page
+        SearchResultsPageModel model = 
+                new SearchResultsPageModel("", request, response, null);
+        ctx.put("searchResults", model);
+        
+        // load standard Velocity stff
+        ContextLoader.setupContext(
+            ctx, RollerRequest.getRollerRequest(request), response );
+        
+        request.setAttribute("zzz_VelocityContext_zzz", ctx); // for testing
+        
+        return getTemplate( "searchresults.vm", "UTF-8" );
+    }
+    
+    /**
+     * If this is not a user-specific search, we need to display the
+     * "generic" search results list.
+     */
+    private Template generalSearchResults(
+            HttpServletRequest request, 
+            HttpServletResponse response, Context ctx) {
+        Template outty = null;
+        Exception pageException = null;
+        try {
+            ContextLoader.setupContext(
+                ctx, RollerRequest.getRollerRequest(request), response );
+            outty = getTemplate( "searchresults.vm", "UTF-8" );
+        } catch (Exception e) {
+            pageException = e;
+            response.setStatus( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
+        }
+        
+        if (pageException != null) {
+            mLogger.error("EXCEPTION: in RollerServlet", pageException);
+            request.setAttribute("DisplayException", pageException);
+        }
+        return outty;
+    }
+}
+
+

Modified: incubator/roller/branches/roller_2.0/tests/org/roller/presentation/SearchServletTest.java
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/tests/org/roller/presentation/SearchServletTest.java?rev=291460&r1=291459&r2=291460&view=diff
==============================================================================
--- incubator/roller/branches/roller_2.0/tests/org/roller/presentation/SearchServletTest.java (original)
+++ incubator/roller/branches/roller_2.0/tests/org/roller/presentation/SearchServletTest.java Sun Sep 25 12:01:45 2005
@@ -8,7 +8,7 @@
 
 import org.roller.presentation.filters.PersistenceSessionFilter;
 import org.roller.presentation.filters.RequestFilter;
-import org.roller.presentation.velocity.SearchServlet;
+import org.roller.presentation.search.SearchServlet;
 
 import com.mockrunner.mock.web.MockHttpServletRequest;
 import com.mockrunner.mock.web.MockServletConfig;

Modified: incubator/roller/branches/roller_2.0/web/WEB-INF/classes/ApplicationResources.properties
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/web/WEB-INF/classes/ApplicationResources.properties?rev=291460&r1=291459&r2=291460&view=diff
==============================================================================
--- incubator/roller/branches/roller_2.0/web/WEB-INF/classes/ApplicationResources.properties (original)
+++ incubator/roller/branches/roller_2.0/web/WEB-INF/classes/ApplicationResources.properties Sun Sep 25 12:01:45 2005
@@ -497,6 +497,8 @@
 <a href="http://google.com">Google</a>.</em>
 macro.searchresults.again=Search Again
 
+error.searchProblem=There was a problem with your search.
+
 # ----------------------------------------------------- Search Results Day Macro
 
 macro.searchresultsday.entrypermalink.title=Permanent link to this weblog entry
@@ -938,11 +940,6 @@
 referers.deletedReferers=Deleted specified referers
 referers.noReferersSpecified=You did not specify any referers to delete
 
-# ------------------------------------------------------------------ Search Form
-
-searchForm.button=Search
-searchForm.alert=Please enter a search term to continue.
-
 # ------------------------------------------------------------------ Tabbed Menu
 
 tabbedmenu.main=Main
@@ -987,7 +984,13 @@
 tabbedmenu.planet.localEntries=Recent Posts
 tabbedmenu.planet.planetEntries=Planet
 
-# ------------------------------------------------------------------------ Theme
+# ---------------------------------------------------------------------- Search
+
+search.title=Search Results
+searchForm.button=Search
+searchForm.alert=Please enter a search term to continue.
+
+# ----------------------------------------------------------------------- Theme
 
 themeEditor.title=Weblog Theme
 themeEditor.subtitle=Select theme for weblog <span>{0}</span>

Modified: incubator/roller/branches/roller_2.0/web/WEB-INF/classes/searchresults.vm
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/web/WEB-INF/classes/searchresults.vm?rev=291460&r1=291459&r2=291460&view=diff
==============================================================================
--- incubator/roller/branches/roller_2.0/web/WEB-INF/classes/searchresults.vm (original)
+++ incubator/roller/branches/roller_2.0/web/WEB-INF/classes/searchresults.vm Sun Sep 25 12:01:45 2005
@@ -3,43 +3,21 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
 ## "no user" versions
 #macro( showSearchResults $dayTemplate )
-    #foreach( $day in $map.keySet() )
-        #set( $entries = $map.get($day) )
+    #foreach( $day in $searchResults.results.keySet() )
+        #set( $entries = $searchResults.results.get($day) )
         #parse( $dayTemplate )
     #end
 #end
 <head>
-    <title>$siteName $text.get("macro.searchresults.results")</title>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-    <script type="text/javascript"
-        src="$ctxPath/theme/scripts/roller.js"></script>
-    <link rel="stylesheet" type="text/css" media="all"
-        href="$ctxPath/themes/base.css" />
-    <link rel="stylesheet" type="text/css" media="all"
-         href="$ctxPath/theme/layout.css" />
-    <link rel="stylesheet" type="text/css" media="all"
-         href="$ctxPath/theme/roller.css" />
-    <link rel="stylesheet" type="text/css" media="all"
-         href="$ctxPath/theme/menu.css" />
 </head>
 <body>
-<div id="header">
-    <span style="width:100%; text-align:right; margin: 3px">
-        #showBasicNavBar( false )
-    </span>
-    <span>
-        #showMenu( "editor-menu.xml" "/menu-tabbed.vm" )
-    </span>
-</div>
 
 <div id="content">
-    #showStatusMessage()
-
     <center>
       <h1>$siteName $text.get("macro.searchresults.results")</h1>
     </center>
 
-    <p>
+  <p>
     #set ( $siteText = "this site")
     #set ( $inUrl = "")
     #if ($username)
@@ -47,24 +25,24 @@
         #set ($inUrl = " inurl:$username" )
     #end
         $text.get("macro.searchresults.searchFor", [$siteText])
-        "<a href="http://dictionary.com/search?q=$utilities.encode($term)"
-        title="$text.get( "macro.searchresults.title", [$term])"
-        class="dictionary">$term</a>".
-
-        $text.get("macro.searchresults.hits_1", [$hits])
-        <a href="http://google.com/search?q=$utilities.encode($term)%20site:${absBaseURL}${inUrl}"
-        class="google">$text.get("macro.searchresults.hits_2")
+        "<a href="http://dictionary.com/search?q=$utilities.encode($searchResults.term)"
+        title="$text.get( "macro.searchresults.title", [$searchResults.term])"
+        class="dictionary">$searchResults.term</a>".
+
+        $text.get("macro.searchresults.hits_1", [$searchResults.hits])
+        <a href="http://google.com/search?q=$utilities.encode($searchResults.term)%20site:${searchResults.baseURL}${inUrl}"
+        class="google">$text.get("macro.searchresults.hits_2")</a>
 
         <form method="get" action="$ctxPath/search"
             style="margin: 5px">
             <input type="text" id="q" name="q" size="31"
-                maxlength="255" value="$term"
+                maxlength="255" value="$searchResults.term"
                 style="padding-left: 1px" />
             <input type="hidden" name="$USERNAME_KEY" value="$!{username}" />
-            #if ($categories)
+            #if ($searchResults.categories)
                 <select name="c">
                 <option value="">- Restrict By Category -</option>
-                #foreach( $cat in $categories )
+                #foreach( $cat in $searchResults.categories )
                     <option #if($cat == $req.getParameter('c'))selected="selected"#end>$cat</option>
                 #end
                 </select>
@@ -76,8 +54,8 @@
         src="$ctxPath/theme/scripts/searchhi.js"></script>
     <br />
 
-    #if ($hits > 0)
-        #set( $map = $searchResults )
+    #if ($searchResults.hits > 0)
+        #set( $map = $searchResults.results )
         #showSearchSummary()
 
         #showSearchResults("searchresults_day.vm")

Modified: incubator/roller/branches/roller_2.0/web/WEB-INF/classes/searchresults_day.vm
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/web/WEB-INF/classes/searchresults_day.vm?rev=291460&r1=291459&r2=291460&view=diff
==============================================================================
--- incubator/roller/branches/roller_2.0/web/WEB-INF/classes/searchresults_day.vm (original)
+++ incubator/roller/branches/roller_2.0/web/WEB-INF/classes/searchresults_day.vm Sun Sep 25 12:01:45 2005
@@ -14,7 +14,7 @@
 
 ## you have to be so damn careful with whitespace in Velocity
 #macro( showCategoryPermalink $entry )
-<a href="${ctxPath}/page/${entry.website.handle}?catname=#$utilities.encode($entry.category.name)"
+<a href="${ctxPath}/page/${entry.website.handle}?catname=$utilities.encode($entry.category.name)"
     title="$text.get( "macro.searchresultsday.categorypermalink.title" )"
     class="entrypermalink">$entry.category.name</a>,
 #end
@@ -26,12 +26,18 @@
     </div>
     #foreach( $entry in $entries )
     <p>
-       <b>$entry.title</b> $entry.text
+       <b>$entry.title</b> 
+       #set($stripped = $utilities.removeHTML($entry.text, true))
+       $utilities.truncateText($stripped, 240, 260, "...")
+
+        #showEntryText($entry.text)
+
+       
        #showEntryPermalink( $entry )
        by #showUserPermalink( $entry )
        on #showTimestamp($entry.pubTime).
        <span style="font-size:x-small;">(<a
-         href="?q=${utilities.encode($term)}&${USERNAME_KEY}=$!{entry.website.creator.userName}"
+         href="?q=${utilities.encode($searchResults.term)}&${USERNAME_KEY}=$!{entry.website.creator.userName}"
          >restrict search</a> to just this blog)</span>
     </p>
     #end

Modified: incubator/roller/branches/roller_2.0/web/WEB-INF/classes/weblog.vm
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/web/WEB-INF/classes/weblog.vm?rev=291460&r1=291459&r2=291460&view=diff
==============================================================================
--- incubator/roller/branches/roller_2.0/web/WEB-INF/classes/weblog.vm (original)
+++ incubator/roller/branches/roller_2.0/web/WEB-INF/classes/weblog.vm Sun Sep 25 12:01:45 2005
@@ -147,98 +147,6 @@
 $absBaseURL/trackback/${website.handle}/$page.link/$utilities.encode($entry.anchor)
 #end
 
-#**
- * Display search form for searching a weblog.  This is only a form, no div
- * or anything around it.
- *#
-#macro( showSearchForm )
-    <form id="searchForm" method="get" action="${ctxPath}/search/${website.handle}"
-        style="margin: 0; padding: 0" onsubmit="return validateSearch(this)">
-        <p>
-          <input type="text" id="q" name="q" size="20"
-              maxlength="255" value="#if($term)$term#end" />
-          #set( $cats = $pageModel.getWeblogCategories("nil") )
-          <select name="c">
-          <option value="">- In Category -</option>
-          #foreach( $cat in $cats )
-              <option #if($cat.name == $req.getParameter('c'))selected="selected"#end>$cat.name</option>
-          #end
-          </select>
-          <input type="submit" value="$text.get( "macro.weblog.searchbutton" )" />
-        </p>
-    </form>
-    <script type="text/javascript">
-        function validateSearch(form) {
-            if (form.q.value == "") {
-                alert("$text.get( "macro.weblog.searchalert" )");
-                form.q.focus();
-                return false;
-            }
-            return true;
-        }
-    </script>
-#end
-
-#**
- * Display search again form
- *#
-#macro( showSearchAgainForm )
-    <div id="searchAgain">
-        $text.get( "macro.weblog.searchdictionary", [$term, $term, $term] )
-
-        $text.get( "macro.weblog.searchhits", [$hits])
-
-        <form method="get" action="${ctxPath}/search/${website.handle}"
-            style="margin: 5px">
-            <input type="text" id="q" name="q" size="31"
-                maxlength="255" value="$term"
-                style="padding-left: 1px" />
-            #set( $cats = $pageModel.getWeblogCategories("nil") )
-            <select name="c">
-            <option value="">- Restrict By Category -</option>
-            #foreach( $cat in $cats )
-              <option #if($cat.name == $req.getParameter('c'))selected="selected"#end>$cat.name</option>
-            #end
-            </select>
-            <input type="submit" value="$text.get( "macro.weblog.searchagain" )" />
-        </form>
-
-        $text.get( "macro.weblog.searchgoogle", [$term, $absBaseURL, $ctxPath, ${website.handle}] )
-    </div>
-    <script type="text/javascript"
-        src="$ctxPath/theme/scripts/searchhi.js"></script>
-#end
-
-#**
- * Displays header like "1 - 10 of 20 found.".
-**#
-#macro( showSearchSummary )
-    #set( $min = $offset + 1 )
-    #set( $max = $offset + $limit )
-    #if( $max > $hits )#set( $max = $hits )#end
-    <h3>
-        $min - $max of $hits found.
-    </h3>
-#end
-
-#**
- * Display list of search result pages (for pagination).
-**#
-#macro( showSearchPager )
-    <h3 style="text-align:center;">
-    #set( $numPages = $hits / $limit )
-    #set( $remainder = $hits % $limit )
-    #if( $remainder > 0 )#set( $numPages = $numPages + 1 )#end
-    #if( $numPages > 1 )
-        #foreach( $pageNum in [1..$numPages] )
-            #set( $i = $pageNum - 1 )
-            #set( $start = $limit * $i )
-            <a href="?q=${utilities.encode($term)}&${USERNAME_KEY}=$!{username}&n=${limit}&o=${start}"
-               >$pageNum</a>#if( $pageNum != $numPages) | #end
-        #end
-    #end
-    </h3>
-#end
 
 #**
  * Shows weblog entries from specified category 
@@ -470,4 +378,106 @@
     dc:date="$entry.pubTime" />
 </rdf:RDF>
 -->
-#end
\ No newline at end of file
+#end
+
+
+
+#** ------------------------------------------------------------------------ 
+Search results macros
+---------------------------------------------------------------------------- *#
+
+#**
+ * Display search form for searching a weblog.  This is only a form, no div
+ * or anything around it.
+ *#
+#macro( showSearchForm )
+    <form id="searchForm" method="get" action="${ctxPath}/search/${website.handle}"
+        style="margin: 0; padding: 0" onsubmit="return validateSearch(this)">
+        <p>
+          <input type="text" id="q" name="q" size="20"
+              maxlength="255" value="#if($term)$term#end" />
+          #set( $cats = $pageModel.getWeblogCategories("nil") )
+          <select name="c">
+          <option value="">- In Category -</option>
+          #foreach( $cat in $cats )
+              <option #if($cat.name == $req.getParameter('c'))selected="selected"#end>$cat.name</option>
+          #end
+          </select>
+          <input type="submit" value="$text.get( "macro.weblog.searchbutton" )" />
+        </p>
+    </form>
+    <script type="text/javascript">
+        function validateSearch(form) {
+            if (form.q.value == "") {
+                alert("$text.get( "macro.weblog.searchalert" )");
+                form.q.focus();
+                return false;
+            }
+            return true;
+        }
+    </script>
+#end
+
+#**
+ * Display search again form
+ *#
+#macro( showSearchAgainForm )
+    <div id="searchAgain">
+        $text.get( "macro.weblog.searchdictionary", [$searchResults.term, $searchResults.term, $searchResults.term] )
+
+        $text.get( "macro.weblog.searchhits", [$searchResults.hits])
+
+        <form method="get" action="${ctxPath}/search/${searchResults.website.handle}"
+            style="margin: 5px">
+            <input type="text" id="q" name="q" size="31"
+                maxlength="255" value="$searchResults.term"
+                style="padding-left: 1px" />
+            #set( $cats = $pageModel.getWeblogCategories("nil") )
+            <select name="c">
+            <option value="">- Restrict By Category -</option>
+            #foreach( $cat in $cats )
+              <option #if($cat.name == $req.getParameter('c'))selected="selected"#end>$cat.name</option>
+            #end
+            </select>
+            <input type="submit" value="$text.get( "macro.weblog.searchagain" )" />
+        </form>
+
+        $text.get( "macro.weblog.searchgoogle", [$searchResults.term, $absBaseURL, $ctxPath, ${searchResults.website.handle}] )
+    </div>
+    <script type="text/javascript"
+        src="$ctxPath/theme/scripts/searchhi.js"></script>
+#end
+
+#**
+ * Displays header like "1 - 10 of 20 found.".
+**#
+#macro( showSearchSummary )
+    #set( $min = $searchResults.offset + 1 )
+    #set( $max = $searchResults.offset + $searchResults.limit )
+    #if( $max > $searchResults.hits )#set( $max = $searchResults.hits )#end
+    <h3>
+        $min - $max of $searchResults.hits found.
+    </h3>
+#end
+
+#**
+ * Display list of search result pages (for pagination).
+**#
+#macro( showSearchPager )
+    <h3 style="text-align:center;">
+    #set( $numPages = $searchResults.hits / $searchResults.limit )
+    #set( $remainder = $searchResults.hits % $searchResults.limit )
+    #if( $remainder > 0 )#set( $numPages = $numPages + 1 )#end
+    #if( $numPages > 1 )
+        #foreach( $pageNum in [1..$numPages] )
+            #set( $i = $pageNum - 1 )
+            #set( $start = $searchResults.limit * $i )
+            <a href="?q=${utilities.encode($searchResults.term)}&${USERNAME_KEY}=$!{username}&n=${searchResults.limit}&o=${start}"
+               >$pageNum</a>#if( $pageNum != $numPages) | #end
+        #end
+    #end
+    </h3>
+#end
+
+
+

Modified: incubator/roller/branches/roller_2.0/web/WEB-INF/tiles-defs.xml
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/web/WEB-INF/tiles-defs.xml?rev=291460&r1=291459&r2=291460&view=diff
==============================================================================
--- incubator/roller/branches/roller_2.0/web/WEB-INF/tiles-defs.xml (original)
+++ incubator/roller/branches/roller_2.0/web/WEB-INF/tiles-defs.xml Sun Sep 25 12:01:45 2005
@@ -86,6 +86,11 @@
 <definition name=".welcome" extends=".tiles-simplepage" >
     <put name="content" value="/website/welcome.jsp" />
 </definition>
+<definition name=".search" extends=".tiles-simplepage" >
+    <put name="content" value="/theme/searchResults.jsp" />
+    <put name="banner"  value="/theme/banner.jsp" />
+    <put name="styles"  value="/theme/css-banner.jsp" />
+</definition>
 
 
 <!-- weblog editor pages (and associates) -->

Modified: incubator/roller/branches/roller_2.0/web/theme/search.jsp
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/web/theme/search.jsp?rev=291460&r1=291459&r2=291460&view=diff
==============================================================================
--- incubator/roller/branches/roller_2.0/web/theme/search.jsp (original)
+++ incubator/roller/branches/roller_2.0/web/theme/search.jsp Sun Sep 25 12:01:45 2005
@@ -13,7 +13,7 @@
      <h3><fmt:message key="mainPage.searchWeblogs" /></h3>
 
      <form id="searchForm" method="get"
-        action="<c:out value="${baseURL}" />/search"
+        action="<c:out value="${baseURL}" />/sitesearch.do"
         style="margin: 0; padding: 0" onsubmit="return validateSearch(this)">
         <input type="text" id="q" name="q" size="20"
             maxlength="255" value="<c:out value="${param.q}" />" />

Added: incubator/roller/branches/roller_2.0/web/theme/searchResults.jsp
URL: http://svn.apache.org/viewcvs/incubator/roller/branches/roller_2.0/web/theme/searchResults.jsp?rev=291460&view=auto
==============================================================================
--- incubator/roller/branches/roller_2.0/web/theme/searchResults.jsp (added)
+++ incubator/roller/branches/roller_2.0/web/theme/searchResults.jsp Sun Sep 25 12:01:45 2005
@@ -0,0 +1,172 @@
+<%@ include file="/taglibs.jsp" %>
+
+<%
+org.roller.presentation.search.SearchResultsPageModel searchResults =
+   (org.roller.presentation.search.SearchResultsPageModel)
+      request.getAttribute("searchResults");       
+%>
+
+<%-- Display the search pager --%>
+    
+<c:choose>
+   <c:when test="${empty searchResults.website}">
+      <c:set var="siteText" value="this site" />
+   </c:when>
+   <c:otherwise>
+      <c:set var="siteText" value="$(searchResults.website.handle}" />
+   </c:otherwise>
+</c:choose>
+  
+<%-- Display search summary --%>
+
+<p>
+    <fmt:message key="macro.searchresults.searchFor" >
+       <fmt:param value="${siteText}" />
+    </fmt:message>
+    
+    <%-- "You searched for blah" and link it to dictionary.com --%>    
+    <fmt:message var="dictionaryUrlTitle" key="macro.searchresults.title">
+       <fmt:param value="${searchResults.term}" />
+    </fmt:message>
+    <c:url var="dictionaryUrl" 
+         value="http://dictionary.com/search?q=${searchResults.term}" />    
+    "<a href='<c:out value="${dictionaryUrl}" />' 
+       title='<c:out value="${dictionaryUrlTitle}" />'
+       class="dictionary"><c:out value="${searchResults.term}" /></a>".
+
+    <%-- "X entries found, try your search on google.com?" --%>
+    <fmt:message key="macro.searchresults.hits_1">
+       <fmt:param value="${searchResults.hits}" />
+    </fmt:message>    
+    <c:url var="googleUrl" 
+         value="http://google.com/search?q=${searchResults.term}%20site:${searchResults.baseURL}" />    
+    <a href='<c:out value="${googleUrl}" />'
+        class="google"><fmt:message key="macro.searchresults.hits_2" /></a>
+
+    <%-- Form to search again --%>
+    <form method="get" action="$ctxPath/search"
+        style="margin: 5px">
+        <input type="text" id="q" name="q" size="31"
+            maxlength="255" value='<c:out value="${searchResults.term}" />'
+            style="padding-left: 1px" />
+        <input type="hidden" name="weblog" value='<c:out value="${request.param.weblog}" />' />
+        
+        <%-- Combobox allows restrict by category --%>
+        <c:if test="${!empty searchResults.categories}">
+            <select name="c">
+            <option value="">- Restrict By Category -</option>
+            <c:forEach var="cat" items="${searchResults.categories}">
+                <c:choose>
+                    <c:when test="${cat == request.param.c}">
+                       <option selected="selected"><c:out value="${cat}" /></option>
+                    </c:when>
+                    <c:otherwise>
+                       <option><c:out value="${cat}" /></option>
+                    </c:otherwise>
+                </c:choose>
+            </c:forEach>
+            </select>
+        </c:if>
+        <input type="submit" value="$text.get("macro.searchresults.again")" />
+    </form>
+</p>
+
+<script type="text/javascript"
+    src="$ctxPath/theme/scripts/searchhi.js"></script>
+<br />
+
+
+<%-- Display results, if we have them --%>
+    
+<c:if test="${searchResults.hits > 0}">
+    <c:set var="min" value="${searchResults.offset + 1}" />
+    <c:set var="max" value="${searchResults.offset + searchResults.limit}" />
+    <c:if test="${max > searchResults.hits}">
+        <c:set var="max" value="${searchResults.hits}" />
+    </c:if>
+    <h3><c:out value="${min}" /> - <c:out value="${max}" /> of <c:out value="${searchResults.hits}" /> found.</h3>
+    <br />
+    
+    <%-- Search results is map of maps, keyed by date objects --%>
+    <% request.setAttribute("keys", searchResults.getResults().keySet()); %>    
+    <%-- Iterate through keys of map --%>
+    <c:forEach var="dayKey" items="${keys}">
+    
+        <%-- Get map of  entries for one day --%>
+        <c:set var="dayMap" value="${searchResults.results[dayKey]}" />        
+        
+            <%-- Display date --%>
+            <h3><c:out value="${dayKey}" /></h3><br />
+            
+            <%-- Loop to display entries --%>
+            <div class="daybox" style="margin: 0px 5px 0px 10px">
+            <c:forEach var="post" items="${dayMap}">
+
+                <a href='<c:out value="${searchResults.baseURL}" /><c:out value="${post.permaLink}" />' class="entryTitle">
+                    <str:truncateNicely upper="90" >
+                       <c:out value="${post.displayTitle}" />
+                    </str:truncateNicely></a>
+                </a><br />
+                
+                <span class="entryDetails">
+                    <a href='<c:out value="${searchResults.baseURL}" />/page/<c:out value="${post.website.handle}" />'>
+                    <str:truncateNicely upper="50" >
+                       <c:out value="${post.website.name}" />
+                    </str:truncateNicely></a> |
+                    <c:out value="${post.category.name}" /> |
+                    <fmt:formatDate value="${post.pubTime}" type="both" dateStyle="medium" timeStyle="medium" /> |
+                    <fmt:message key="mainPage.postedBy" />
+                    <c:out value="${post.creator.userName}" />
+                    <c:if test="${!empty post.link}">
+                       | <a href='<c:out value="${post.link}" />' class="entryDetails"><fmt:message key="mainPage.link" /></a>
+                    </c:if>
+                    <br />
+                </span>
+                
+               <span class="entryDescription">
+                   <roller:ApplyPlugins name="post" scope="page" stripHtml="true" maxLength="120" skipFlag="true" />
+               </span>
+        
+               <span style="font-size:x-small;">(<a
+                 href='<c:url value="?q=${searchResults.term}&weblog=${post.website.handle}" />'>restrict search</a> 
+                 to just this blog)
+               </span>
+                     
+            </c:forEach>
+            </div> <%-- daybox --%>
+            <br />
+            <br />
+        </div>
+                
+    </c:forEach>
+    
+    
+    <%-- Display the search pager --%>
+    
+    <h3 style="text-align:center;">
+    <c:set var="numPages" value="${searchResults.hits / searchResults.limit}" />
+    <c:set var="remainder" value="${searchResults.hits % searchResults.limit}" />
+    <c:if test="${remainder > 0}">
+       <c:set var="numPages" value="${numPages + 1}" />
+    </c:if>
+    <c:if test="${numPages > 1}">
+    
+       <br />
+       <br />
+       <c:forEach var="pageNum" begin="1" end="${numPages}" >
+          <c:set var="i" value="${pageNum - 1}" />
+          <c:set var="start" value="${searchResults.limit * i}" />
+          <a href='<c:url value="?q=${searchResults.term}&weblog=${request.param.handle}&n=${searchResults.limit}&o=${start}"/>'>
+             <c:out value="${pageNum}" />
+          </a> 
+          <c:if test="${pageNum != numPages}">|</c:if>
+       </c:forEach>
+       <br />
+       <br />
+
+    </c:if>
+    </h3> 
+    
+</c:if>
+
+