File Source: SearchResultsModel.java

         /* 
    P/P   *  Method: org.apache.roller.weblogger.ui.rendering.model.SearchResultsModel__static_init
          */
     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   *  contributor license agreements.  The ASF licenses this file to You
     4   * under the Apache License, Version 2.0 (the "License"); you may not
     5   * use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.  For additional information regarding
    15   * copyright in this work, please see the NOTICE file in the top level
    16   * directory of this distribution.
    17   */
    18  
    19  package org.apache.roller.weblogger.ui.rendering.model;
    20  
    21  import java.io.IOException;
    22  import java.sql.Timestamp;
    23  import java.util.Date;
    24  import java.util.Map;
    25  import java.util.Set;
    26  import java.util.TreeMap;
    27  import java.util.TreeSet;
    28  import org.apache.commons.collections.comparators.ReverseComparator;
    29  import org.apache.commons.lang.StringUtils;
    30  import org.apache.commons.lang.StringEscapeUtils;
    31  import org.apache.lucene.document.Document;
    32  import org.apache.lucene.search.Hits;
    33  import org.apache.roller.weblogger.WebloggerException;
    34  import org.apache.roller.weblogger.business.search.FieldConstants;
    35  import org.apache.roller.weblogger.business.search.operations.SearchOperation;
    36  import org.apache.roller.weblogger.config.WebloggerRuntimeConfig;
    37  import org.apache.roller.weblogger.business.search.IndexManager;
    38  import org.apache.roller.weblogger.business.Weblogger;
    39  import org.apache.roller.weblogger.business.WebloggerFactory;
    40  import org.apache.roller.weblogger.business.WeblogManager;
    41  import org.apache.roller.weblogger.pojos.WeblogEntry;
    42  import org.apache.roller.weblogger.pojos.WeblogEntryWrapperComparator;
    43  import org.apache.roller.weblogger.pojos.wrapper.WeblogCategoryWrapper;
    44  import org.apache.roller.weblogger.pojos.wrapper.WeblogEntryWrapper;
    45  import org.apache.roller.weblogger.ui.rendering.pagers.SearchResultsPager;
    46  import org.apache.roller.weblogger.ui.rendering.pagers.WeblogEntriesPager;
    47  import org.apache.roller.weblogger.ui.rendering.util.WeblogSearchRequest;
    48  import org.apache.roller.util.DateUtil;
    49  import org.apache.roller.weblogger.business.URLStrategy;
    50  import org.apache.roller.weblogger.util.I18nMessages;
    51  import org.apache.roller.weblogger.util.Utilities;
    52  
    53  
    54  /**
    55   * Extends normal page renderer model to represent search results.
    56   *
    57   * Also adds some new methods which are specific only to search results.
    58   */
         /* 
    P/P   *  Method: void org.apache.roller.weblogger.ui.rendering.model.SearchResultsModel()
          * 
          *  Postconditions:
          *    this.categories == &new TreeSet(SearchResultsModel#3)
          *    this.commentForm == null
          *    this.errorMessage == null
          *    this.pageRequest == null
          *    this.pager == null
          *    this.requestParameters == null
          *    this.searchRequest == null
          *    this.urlStrategy == null
          *    this.weblog == null
          *    this.hits == 0
          *    ...
          */
    59  public class SearchResultsModel extends PageModel {
    60      
    61      public static final int RESULTS_PER_PAGE = 10;
    62      
    63      
    64      // the original search request
    65      WeblogSearchRequest searchRequest = null;
    66      private URLStrategy urlStrategy = null;
    67      
    68      // the actual search results mapped by Day -> Set of entries
    69      private TreeMap results = new TreeMap(new ReverseComparator());
    70      
    71      // the pager used by the 3.0+ rendering system
    72      private SearchResultsPager pager = null;
    73      
    74      private int hits = 0;
    75      private int offset = 0;
    76      private int limit = 0;
    77      private Set categories = new TreeSet();
    78      private boolean websiteSpecificSearch = true;
    79      private String errorMessage = null;
    80      
    81      
    82      public void init(Map initData) throws WebloggerException {
    83          
    84          // we expect the init data to contain a searchRequest object
                 /* 
    P/P           *  Method: void init(Map)
                  * 
                  *  Preconditions:
                  *    initData != null
                  *    org/apache/roller/weblogger/util/I18nMessages.messagesMap != null
                  *    (soft) init'ed(this.hits)
                  *    (soft) init'ed(this.limit)
                  *    (soft) init'ed(this.offset)
                  *    (soft) init'ed(this.websiteSpecificSearch)
                  *    (soft) this.results != null
                  * 
                  *  Presumptions:
                  *    getMessages(...).bundle != null
                  *    java.util.Map:get(...)@81 != null
                  *    java.util.Map:get(...)@85 != null
                  *    org.apache.roller.weblogger.business.Weblogger:getIndexManager(...)@106 != null
                  *    org.apache.roller.weblogger.business.WebloggerFactory:getWeblogger(...)@106 != null
                  *    ...
                  * 
                  *  Postconditions:
                  *    this.categories == One-of{old this.categories, &new TreeSet(convertHitsToEntries#1)}
                  *    init'ed(this.commentForm)
                  *    possibly_updated(this.errorMessage)
                  *    (soft) init'ed(this.hits)
                  *    (soft) init'ed(this.limit)
                  *    (soft) init'ed(this.offset)
                  *    this.pageRequest != null
                  *    this.pager in Addr_Set{&new SearchResultsPager(init#1),&new SearchResultsPager(init#3)}
                  *    init'ed(this.requestParameters)
                  *    (soft) this.searchRequest != null
                  *    ...
                  * 
                  *  Test Vectors:
                  *    java.util.Map:get(...)@91: Inverse{null}, Addr_Set{null}
                  *    org.apache.commons.lang.StringUtils:isNotEmpty(...)@117: {0}, {1}
                  *    org.apache.roller.weblogger.business.search.operations.SearchOperation:getResultsCount(...)@124: {-231..-2, 0..232-1}, {-1}
                  *    org.apache.roller.weblogger.config.WebloggerRuntimeConfig:isSiteWideWeblog(...)@111: {0}, {1}
                  *    org.apache.roller.weblogger.ui.rendering.util.WeblogSearchRequest:getQuery(...)@100: Inverse{null}, Addr_Set{null}
                  */
    85          searchRequest = (WeblogSearchRequest) initData.get("searchRequest");
    86          if(searchRequest == null) {
    87              throw new WebloggerException("expected searchRequest from init data");
    88          }
    89          
    90          // look for url strategy
    91          urlStrategy = (URLStrategy) initData.get("urlStrategy");
    92          if(urlStrategy == null) {
    93              urlStrategy = WebloggerFactory.getWeblogger().getUrlStrategy();
    94          }
    95          
    96          // let parent initialize
    97          super.init(initData);
    98          
    99          // if there is no query, then we are done
   100          if(searchRequest.getQuery() == null) {
   101              pager = new SearchResultsPager(urlStrategy, searchRequest, results, false);
   102              return;
   103          }
   104          
   105          // setup the search
   106          IndexManager indexMgr = WebloggerFactory.getWeblogger().getIndexManager();
   107          
   108          SearchOperation search = new SearchOperation(indexMgr);
   109          search.setTerm(searchRequest.getQuery());
   110          
   111          if(WebloggerRuntimeConfig.isSiteWideWeblog(searchRequest.getWeblogHandle())) {
   112              this.websiteSpecificSearch = false;
   113          } else {
   114              search.setWebsiteHandle(searchRequest.getWeblogHandle());
   115          }
   116          
   117          if(StringUtils.isNotEmpty(searchRequest.getWeblogCategoryName())) {
   118              search.setCategory(searchRequest.getWeblogCategoryName());
   119          }
   120          
   121          // execute search
   122          indexMgr.executeIndexOperationNow(search);
   123          
   124          if (search.getResultsCount() == -1) {
   125              // this means there has been a parsing (or IO) error
   126              this.errorMessage = I18nMessages.getMessages(searchRequest.getLocaleInstance()).getString("error.searchProblem");
   127          } else {
   128              Hits hits = search.getResults();
   129              this.hits = search.getResultsCount();
   130              
   131              // Convert the Hits into WeblogEntryData instances.
   132              convertHitsToEntries(hits);
   133          }
   134          
   135          // search completed, setup pager based on results
   136          pager = new SearchResultsPager(urlStrategy, searchRequest, results, (hits > (offset+limit)));
   137      }
   138      
   139      /**
   140       * Is this page showing search results?
   141       */
   142      public boolean isSearchResults() {
                 /* 
    P/P           *  Method: bool isSearchResults()
                  * 
                  *  Postconditions:
                  *    return_value == 1
                  */
   143          return true;
   144      }
   145      
   146      // override page model and return search results pager
   147      public WeblogEntriesPager getWeblogEntriesPager() {
                 /* 
    P/P           *  Method: WeblogEntriesPager getWeblogEntriesPager()
                  * 
                  *  Preconditions:
                  *    init'ed(this.pager)
                  * 
                  *  Postconditions:
                  *    return_value == this.pager
                  *    init'ed(return_value)
                  */
   148          return pager;
   149      }
   150      
   151      // override page model and return search results pager
   152      public WeblogEntriesPager getWeblogEntriesPager(String category) {
                 /* 
    P/P           *  Method: WeblogEntriesPager getWeblogEntriesPager(String)
                  * 
                  *  Preconditions:
                  *    init'ed(this.pager)
                  * 
                  *  Postconditions:
                  *    return_value == this.pager
                  *    init'ed(return_value)
                  */
   153          return pager;
   154      }
   155      
   156      private void convertHitsToEntries(Hits hits) throws WebloggerException {
   157          
   158          // determine offset
                 /* 
    P/P           *  Method: void convertHitsToEntries(Hits)
                  * 
                  *  Preconditions:
                  *    hits != null
                  *    this.searchRequest != null
                  *    (soft) this.results != null
                  *    (soft) init'ed(this.websiteSpecificSearch)
                  * 
                  *  Presumptions:
                  *    org.apache.lucene.document.Document:getField(...)@184 != null
                  *    org.apache.lucene.document.Document:getField(...)@189 != null
                  *    org.apache.lucene.document.Document:getField(...)@193 != null
                  *    org.apache.lucene.document.Document:getField(...)@197 != null
                  *    org.apache.lucene.document.Field:stringValue(...)@184 != null
                  *    ...
                  * 
                  *  Postconditions:
                  *    this.categories == One-of{old this.categories, &new TreeSet(convertHitsToEntries#1)}
                  *    init'ed(this.limit)
                  *    (soft) this.offset in -231+8..232-6
                  *    new TreeSet(convertHitsToEntries#1) num objects == 1
                  *    (soft) this.offset + this.limit in -231..232-1
                  * 
                  *  Test Vectors:
                  *    this.websiteSpecificSearch: {0}, {1}
                  *    java.lang.String:equals(...)@186: {0}, {1}
                  *    java.sql.Timestamp:before(...)@205: {0}, {1}
                  *    java.util.TreeSet:size(...)@210: {-231..0}, {1..232-1}
                  *    org.apache.lucene.document.Document:getField(...)@196: Addr_Set{null}, Inverse{null}
                  */
   159          this.offset = searchRequest.getPageNum() * RESULTS_PER_PAGE;
   160          if(this.offset >= hits.length()) {
   161              this.offset = 0;
   162          }
   163          
   164          // determine limit
   165          this.limit = RESULTS_PER_PAGE;
   166          if(this.offset + this.limit > hits.length()) {
   167              this.limit = hits.length() - this.offset;
   168          }
   169          
   170          try {
   171              TreeSet categories = new TreeSet();
   172              Weblogger roller = WebloggerFactory.getWeblogger();
   173              WeblogManager weblogMgr = roller.getWeblogManager();
   174              
   175              WeblogEntry entry = null;
   176              Document doc = null;
   177              String handle = null;
   178              Timestamp now = new Timestamp(new Date().getTime());
   179              for(int i = offset; i < offset+limit; i++) {
   180                  
   181                  entry = null; // reset for each iteration
   182                  
   183                  doc = hits.doc(i);
   184                  handle = doc.getField(FieldConstants.WEBSITE_HANDLE).stringValue();
   185                  
   186                  if(websiteSpecificSearch &&
   187                          handle.equals(searchRequest.getWeblogHandle())) {
   188                      
   189                      entry = weblogMgr.getWeblogEntry(
   190                              doc.getField(FieldConstants.ID).stringValue());
   191                  } else {
   192                      
   193                      entry = weblogMgr.getWeblogEntry(
   194                              doc.getField(FieldConstants.ID).stringValue());
   195                      
   196                      if (doc.getField(FieldConstants.CATEGORY) != null) {
   197                          categories.add(
   198                                  doc.getField(FieldConstants.CATEGORY).stringValue());
   199                      }
   200                  }
   201                  
   202                  // maybe null if search result returned inactive user
   203                  // or entry's user is not the requested user.
   204                  // but don't return future posts
   205                  if (entry != null && entry.getPubTime().before(now)) {
   206                      addEntryToResults(WeblogEntryWrapper.wrap(entry, urlStrategy));
   207                  }
   208              }
   209              
   210              if(categories.size() > 0) {
   211                  this.categories = categories;
   212              }
   213          } catch(IOException e) {
   214              throw new WebloggerException(e);
   215          }
   216      }
   217      
   218      
   219      private void addEntryToResults(WeblogEntryWrapper entry) {
   220          
   221          // convert entry's each date to midnight (00m 00h 00s)
                 /* 
    P/P           *  Method: void addEntryToResults(WeblogEntryWrapper)
                  * 
                  *  Preconditions:
                  *    entry != null
                  *    entry.pojo != null
                  *    this.results != null
                  * 
                  *  Test Vectors:
                  *    java.util.TreeMap:get(...)@226: Inverse{null}, Addr_Set{null}
                  */
   222          Date midnight = DateUtil.getStartOfDay(entry.getPubTime());
   223          
   224          // ensure we do not get duplicates from Lucene by
   225          // using a Set Collection.  Entries sorted by pubTime.
   226          TreeSet set = (TreeSet) this.results.get(midnight);
   227          if (set == null) {
   228              // date is not mapped yet, so we need a new Set
   229              set = new TreeSet( new WeblogEntryWrapperComparator());
   230              this.results.put(midnight, set);
   231          }
   232          set.add(entry);
   233      }
   234      
   235      
   236      public String getTerm() {
                 /* 
    P/P           *  Method: String getTerm()
                  * 
                  *  Preconditions:
                  *    this.searchRequest != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   237          String query = searchRequest.getQuery();
   238          return (query == null) ? "" : StringEscapeUtils.escapeXml(Utilities.escapeHTML(query));
   239      }
   240  
   241      public String getRawTerm() {
                 /* 
    P/P           *  Method: String getRawTerm()
                  * 
                  *  Preconditions:
                  *    this.searchRequest != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   242          return (searchRequest.getQuery() == null) ? "" : searchRequest.getQuery();
   243      }
   244  
   245      public int getHits() {
                 /* 
    P/P           *  Method: int getHits()
                  * 
                  *  Preconditions:
                  *    init'ed(this.hits)
                  * 
                  *  Postconditions:
                  *    return_value == this.hits
                  *    init'ed(return_value)
                  */
   246          return hits;
   247      }
   248  
   249      public int getOffset() {
                 /* 
    P/P           *  Method: int getOffset()
                  * 
                  *  Preconditions:
                  *    init'ed(this.offset)
                  * 
                  *  Postconditions:
                  *    return_value == this.offset
                  *    init'ed(return_value)
                  */
   250          return offset;
   251      }
   252  
   253      public int getLimit() {
                 /* 
    P/P           *  Method: int getLimit()
                  * 
                  *  Preconditions:
                  *    init'ed(this.limit)
                  * 
                  *  Postconditions:
                  *    return_value == this.limit
                  *    init'ed(return_value)
                  */
   254          return limit;
   255      }
   256  
   257      public TreeMap getResults() {
                 /* 
    P/P           *  Method: TreeMap getResults()
                  * 
                  *  Preconditions:
                  *    init'ed(this.results)
                  * 
                  *  Postconditions:
                  *    return_value == this.results
                  *    init'ed(return_value)
                  */
   258          return results;
   259      }
   260  
   261      public Set getCategories() {
                 /* 
    P/P           *  Method: Set getCategories()
                  * 
                  *  Preconditions:
                  *    init'ed(this.categories)
                  * 
                  *  Postconditions:
                  *    return_value == this.categories
                  *    init'ed(return_value)
                  */
   262          return categories;
   263      }
   264  
   265      public boolean isWebsiteSpecificSearch() {
                 /* 
    P/P           *  Method: bool isWebsiteSpecificSearch()
                  * 
                  *  Preconditions:
                  *    init'ed(this.websiteSpecificSearch)
                  * 
                  *  Postconditions:
                  *    return_value == this.websiteSpecificSearch
                  *    init'ed(return_value)
                  */
   266          return websiteSpecificSearch;
   267      }
   268  
   269      public String getErrorMessage() {
                 /* 
    P/P           *  Method: String getErrorMessage()
                  * 
                  *  Preconditions:
                  *    init'ed(this.errorMessage)
                  * 
                  *  Postconditions:
                  *    return_value == this.errorMessage
                  *    init'ed(return_value)
                  */
   270          return errorMessage;
   271      }
   272      
   273      public String getWeblogCategoryName() {
                 /* 
    P/P           *  Method: String getWeblogCategoryName()
                  * 
                  *  Preconditions:
                  *    this.searchRequest != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   274          return searchRequest.getWeblogCategoryName();
   275      }
   276      
   277      public WeblogCategoryWrapper getWeblogCategory() {
                 /* 
    P/P           *  Method: WeblogCategoryWrapper getWeblogCategory()
                  * 
                  *  Preconditions:
                  *    this.searchRequest != null
                  * 
                  *  Postconditions:
                  *    return_value == One-of{&new WeblogCategoryWrapper(wrap#1), null}
                  *    return_value in Addr_Set{null,&new WeblogCategoryWrapper(wrap#1)}
                  *    new WeblogCategoryWrapper(wrap#1) num objects <= 1
                  *    new WeblogCategoryWrapper(wrap#1).pojo != null
                  *    new WeblogCategoryWrapper(wrap#1).urlStrategy == this.urlStrategy
                  *    init'ed(new WeblogCategoryWrapper(wrap#1).urlStrategy)
                  * 
                  *  Test Vectors:
                  *    org.apache.roller.weblogger.ui.rendering.util.WeblogSearchRequest:getWeblogCategory(...)@278: Addr_Set{null}, Inverse{null}
                  */
   278          if(searchRequest.getWeblogCategory() != null) {
   279              return WeblogCategoryWrapper.wrap(searchRequest.getWeblogCategory(), urlStrategy);
   280          }
   281          return null;
   282      }
   283      
   284  }








SofCheck Inspector Build Version : 2.18479
SearchResultsModel.java 2009-Jan-02 14:25:24
SearchResultsModel.class 2009-Sep-04 03:12:44