The Search Class


The simplest approach to creating a search server is to follow the Single-Responsibility Principle and first design a class that supports a single search. Once it works, you can concern yourself with the multithreading needs. The benefit is that in keeping each search as a separate object, you have fewer concerns with respect to shared data.

The SearchTest class tests a few possible cases:

 package sis.search; import junit.framework.TestCas e; import java.io.*; public class SearchTest extends TestCase {    private static final String URL = "http://www.langrsoft.com";    public void testCreate() throws IOException {       Search search = new Search(URL, "x");       assertEquals(URL, search.getUrl());       assertEquals("x", search.getText());    }    public void testPositiveSearch() throws IOException {       Search search = new Search(URL, "Jeff Langr");       search.execute();       assertTrue(search.matches() >= 1);       assertFalse(search.errored());    }    public void testNegativeSearch() throws IOException {       final String unlikelyText = "mama cass elliott";       Search search = new Search(URL, unlikelyText);       search.execute();       assertEquals(0, search.matches());       assertFalse(search.errored());    }    public void testErroredSearch() throws IOException {       final String badUrl = URL + "/z2468.html";       Search search = new Search(badUrl, "whatever");       search.execute();       assertTrue(search.errored());       assertEquals(FileNotFoundException.class,          search.getError().getClass());    } } 

The implementation a:

 package sis.search; import java.net.*; import java.io.*; import sis.util.*; public class Search {    private URL url;    private String searchString;    private int matches = 0;    private Exception exception = null;    public Search(String urlString, String searchString)           throws IOException {       this.url = new URL(urlString);       this.searchString = searchString;    }    public String getText() {       return searchString;    }    public String getUrl() {       return url.toString();    }    public int matches() {       return matches;    }    public boolean errored() {       return exception != null;    }    public Exception getError() {       return exception;    }        public void execute() {       try {          searchUrl();       }       catch (IOException e) {          exception = e;       }    }        private void searchUrl() throws IOException {       URLConnection connection = url.openConnection();       InputStream input = connection.getInputStream();       BufferedReader reader = null;       try {          reader = new BufferedReader(new InputStreamReader(input));          String line;          while ((line = reader.readLine()) != null)             matches += StringUtil.occurrences(line, searchString);       }       finally {          if (reader != null)             reader.close();       }    } } 

The method searchUrl in Search uses a the class java.net.URL to obtain a java.net.URLConnection object. A URLConnection is used to establish communication between the client and the actual URL. Once you send the openConnection message to a URLConnection, you can send the message getInputStream to obtain an InputStream reference. The remainder of the method uses Java IO code (see Lesson 11) to search the file.

Currently, searchUrl invokes the StringUtil method occurrences to count the number of matches within each line read from the input stream. Here are StringUtilTest and StringUtil.

 // StringUtilTest.java package sis.util; import junit.framework.*; public class StringUtilTest extends TestCase {    private static final String TEXT = "this is it, isn't it";    public void testOccurrencesOne() {       assertEquals(1, StringUtil.occurrences(TEXT, "his"));    }    public void testOccurrencesNone() {       assertEquals(0, StringUtil.occurrences(TEXT, "smelt"));    }    public void testOccurrencesMany() {       assertEquals(3, StringUtil.occurrences(TEXT, "is"));       assertEquals(2, StringUtil.occurrences(TEXT, "it"));    }    public void testOccurrencesSearchStringTooLarge() {       assertEquals(0, StringUtil.occurrences(TEXT, TEXT + "sdfas"));    } } // StringUtil.java package sis.util; public class StringUtil {    static public int occurrences(String string, String substring) {       int occurrences = 0;       int length = substring.length();       final boolean ignoreCase = true;       for (int i = 0; i < string.length() - substring.length() + 1; i++)          if (string.regionMatches(ignoreCase, i, substring, 0, length))             occurrences++;       return occurrences;    } } 

Another solution would be to use Java's regular expression (regex) API. See Additional Lesson III for a discussion of regex.



Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net