Coverage Report - net.sourceforge.pebble.webservice.SearchAPIHandler
 
Classes in this File Line Coverage Branch Coverage Complexity
SearchAPIHandler
0%
0/67
0%
0/18
3.75
 
 1  
 
 2  
 /*
 3  
  * Copyright (c) 2003-2011, Simon Brown
 4  
  * All rights reserved.
 5  
  *
 6  
  * Redistribution and use in source and binary forms, with or without
 7  
  * modification, are permitted provided that the following conditions are met:
 8  
  *
 9  
  *   - Redistributions of source code must retain the above copyright
 10  
  *     notice, this list of conditions and the following disclaimer.
 11  
  *
 12  
  *   - Redistributions in binary form must reproduce the above copyright
 13  
  *     notice, this list of conditions and the following disclaimer in
 14  
  *     the documentation and/or other materials provided with the
 15  
  *     distribution.
 16  
  *
 17  
  *   - Neither the name of Pebble nor the names of its contributors may
 18  
  *     be used to endorse or promote products derived from this software
 19  
  *     without specific prior written permission.
 20  
  *
 21  
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 22  
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 23  
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 24  
  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 25  
  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 26  
  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 27  
  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 28  
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 29  
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 30  
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 31  
  * POSSIBILITY OF SUCH DAMAGE.
 32  
  */
 33  
 
 34  
 package net.sourceforge.pebble.webservice;
 35  
 
 36  
 import java.util.Hashtable;
 37  
 import java.util.Iterator;
 38  
 import java.util.List;
 39  
 import java.util.Map;
 40  
 import java.util.Vector;
 41  
 
 42  
 import net.sourceforge.pebble.domain.Blog;
 43  
 import net.sourceforge.pebble.domain.BlogEntry;
 44  
 import net.sourceforge.pebble.domain.BlogService;
 45  
 import net.sourceforge.pebble.domain.Category;
 46  
 import net.sourceforge.pebble.search.SearchHit;
 47  
 import net.sourceforge.pebble.search.SearchResults;
 48  
 import net.sourceforge.pebble.util.Pageable;
 49  
 
 50  
 import org.apache.commons.logging.Log;
 51  
 import org.apache.commons.logging.LogFactory;
 52  
 
 53  
 
 54  
 /**
 55  
  * Extension to allow search and query of Blog posting via XML-RPC.
 56  
  *
 57  
  * @author tcp@favoritemedium.com
 58  
  */
 59  0
 public class SearchAPIHandler extends AbstractAPIHandler {
 60  
 
 61  
     static final String URL = "url";
 62  
     static final String BLOG_ID = "blogid";
 63  
     static final String BLOG_NAME = "blogName";
 64  
     static final String DATE_CREATED = "dateCreated";
 65  
     static final String USER_ID = "userId";
 66  
     static final String POST_ID = "postid";
 67  
     static final String CONTENT = "content";
 68  
 
 69  
     static final String TITLE_START_DELIMITER = "<title>";
 70  
     static final String TITLE_END_DELIMITER = "</title>";
 71  
     static final String CATEGORY_START_DELIMITER = "<category>";
 72  
     static final String CATEGORY_END_DELIMITER = "</category>";
 73  
     static final char BLOG_ID_SEPARATOR = '/';
 74  
 
 75  
     static final int PAGE_SIZE = 20;
 76  
 
 77  
 
 78  
     /** the log used by this class */
 79  0
     private static Log log = LogFactory.getLog(SearchAPIHandler.class);
 80  
 
 81  
 
 82  
     /**
 83  
      * Search blog for specific string.
 84  
      * 
 85  
      * @param blogid    the ID of the blog (ignored)
 86  
      * @param username  the username used for logging in via XML-RPC
 87  
      * @param password  the password used for logging in via XML-RPC
 88  
      */
 89  
     public Vector search(String blogid, String username, String password, 
 90  
                         String searchString, String sortBy) {
 91  0
         log.debug("search.search(" +
 92  
             blogid + ", " +
 93  
             username + ", xxxxxx, \"" +
 94  
             searchString + "," + 
 95  
             sortBy + "\")");
 96  
 
 97  0
         Vector posts = new Vector();
 98  
         try {
 99  
 
 100  0
             Blog blog = getBlogWithBlogId(blogid);
 101  0
             SearchResults result = blog.getSearchIndex().search( searchString );
 102  
 
 103  0
             if ( sortBy != null && sortBy.equalsIgnoreCase("date") ) {
 104  0
                 result.sortByDateDescending();
 105  
             } else {
 106  0
                 result.sortByScoreDescending();
 107  
             }
 108  
 
 109  0
             List<SearchHit> hits = result.getHits();
 110  0
             BlogService service = new BlogService();
 111  
 
 112  0
             for (SearchHit hit : hits) {
 113  0
                 BlogEntry entry = service.getBlogEntry(hit.getBlog(), hit.getId());
 114  0
                 adaptBlogEntry(entry);
 115  0
                 posts.add(adaptBlogEntry(entry));
 116  0
             }
 117  0
             posts.add( searchResultSummary(hits, sortBy, searchString, 0, 0) );
 118  
 
 119  0
         } catch (Exception ex) {
 120  0
             log.error(ex);
 121  0
         }
 122  0
         return posts;
 123  
     }
 124  
 
 125  
     /**
 126  
      * Search blog for specific string with pagable parameters
 127  
      * 
 128  
      * @param blogid    the ID of the blog (ignored)
 129  
      * @param username  the username used for logging in via XML-RPC
 130  
      * @param password  the password used for logging in via XML-RPC
 131  
      */
 132  
     public Vector search(String blogid, String username, String password, 
 133  
                         String searchString, String sortBy, int pageSize, int offset) {
 134  0
         log.debug("search.search(" +
 135  
             blogid + ", " +
 136  
             username + ", xxxxxx, \"" +
 137  
             searchString + "," + 
 138  
             sortBy + "\")");
 139  
 
 140  
 
 141  0
         Vector posts = new Vector();
 142  
         try {
 143  
 
 144  0
             Blog blog = getBlogWithBlogId(blogid);
 145  0
             SearchResults result = blog.getSearchIndex().search( searchString );
 146  
             
 147  0
             if ( sortBy != null && sortBy.equalsIgnoreCase("date") ) {
 148  0
                 result.sortByDateDescending();
 149  
             } else {
 150  0
                 result.sortByScoreDescending();
 151  
             }
 152  
 
 153  0
             if ( pageSize <= 0 ) 
 154  0
                 pageSize = PAGE_SIZE;
 155  
 
 156  0
             List<SearchHit> hits = result.getHits();
 157  0
             Pageable pageable = new Pageable(hits);
 158  0
             pageable.setPageSize(pageSize);
 159  0
             pageable.setPage(offset);
 160  0
             List<SearchHit> subList = pageable.getListForPage();
 161  
 
 162  0
             BlogService service = new BlogService();
 163  
 
 164  0
             for (SearchHit hit : subList ) {
 165  0
                 BlogEntry entry = service.getBlogEntry(hit.getBlog(), hit.getId());
 166  0
                 adaptBlogEntry(entry);
 167  0
                 posts.add(adaptBlogEntry(entry));
 168  0
             }
 169  0
             posts.add( searchResultSummary(subList, sortBy, searchString, pageSize, offset) );
 170  
 
 171  0
         } catch (Exception ex) {
 172  0
             log.error(ex);
 173  0
         }
 174  0
         return posts;
 175  
     }
 176  
 
 177  
     /**
 178  
      * Helper method to adapt a blog entry into an XML-RPC compatible struct.
 179  
      * Since the Blogger API doesn't support titles, the title is wrapped in
 180  
      * &lt;title&gt;&lt;/title&gt; tags.
 181  
      *
 182  
      * @param entry   the BlogEntry to adapt
 183  
      * @return  a Hashtable representing the major properties of the entry
 184  
      */
 185  
     private Hashtable adaptBlogEntry(BlogEntry entry) {
 186  0
         Hashtable post = new Hashtable();
 187  0
         String categories = "";
 188  0
         Iterator it = entry.getCategories().iterator();
 189  0
         while (it.hasNext()) {
 190  0
             Category category = (Category)it.next();
 191  0
             categories += category.getId();
 192  0
             if (it.hasNext()) {
 193  0
                 categories += ",";
 194  
             }
 195  0
         }
 196  0
         post.put(DATE_CREATED, entry.getDate());
 197  0
         post.put(USER_ID, entry.getAuthor());
 198  0
         post.put(POST_ID, formatPostId(entry.getBlog().getId(), entry.getId()));
 199  0
         post.put(CONTENT, TITLE_START_DELIMITER + entry.getTitle() + TITLE_END_DELIMITER
 200  
                 + CATEGORY_START_DELIMITER + categories + CATEGORY_END_DELIMITER + entry.getBody());
 201  
 
 202  0
         return post;
 203  
     }
 204  
 
 205  
     /**
 206  
      * Auto create a Map of search result summary.
 207  
      * @param result of the search hits.
 208  
      */
 209  
     private Map searchResultSummary(List<SearchHit> result, String sortBy,
 210  
                                         String query, int pageIndex, int offset) {
 211  0
         Map data = new Hashtable();
 212  0
         data.put("size", result.size() );
 213  0
         data.put("sortBy", sortBy);
 214  0
         data.put("index", pageIndex);
 215  0
         data.put("offset", offset);
 216  0
         data.put("query", query);
 217  
 
 218  0
         return data;
 219  
     }
 220  
 
 221  
 }