View Javadoc

1   package org.paneris.bibliomania.metasearch;
2   
3   import java.util.Enumeration;
4   import java.util.NoSuchElementException;
5   import java.util.Vector;
6   
7   import org.melati.poem.transaction.ToTidyList;
8   import org.paneris.bibliomania.BookStocking;
9   import org.paneris.bibliomania.Bookshop;
10  
11  public class Metasearch implements ToTidyList.Closeable {
12  
13    private Bookshop[] shops;
14    private String title;
15    private String author;
16    private ToTidyList toTidy;
17    private SearchThread[] threads;
18    private Vector results = new Vector();
19    private int runningThreads = 0;
20  
21    private class SearchThread extends Thread {
22      private Bookshop shop;
23  
24      public SearchThread(Bookshop shop) {
25        this.shop = shop;
26      }
27  
28      public void run() {
29        try {
30          Enumeration books =
31            shop.backend.booksMatching(shop, title, author, "", "", toTidy);
32          while (books.hasMoreElements()) {
33            BookStocking stocking = (BookStocking)books.nextElement();
34            shop.backend.resolve(stocking);
35            synchronized (results) {
36              results.addElement(stocking);
37              results.notifyAll();
38            }
39          }
40        } catch (Exception e) {
41          System.err.println("Metasearch.SearchThread: " + e);
42        } finally {
43          synchronized (results) {
44            --runningThreads;
45            results.notifyAll();
46            if (runningThreads <= 0) {
47              synchronized (Metasearch.this) {
48                Metasearch.this.notifyAll();
49              }
50            }
51          }
52        }
53      }
54  
55      public void close() {
56        try {
57          stop();
58        } catch (Exception e) {
59        }
60      }
61    }
62  
63    private class HitsEnumeration implements Enumeration {
64  
65      private int nextResultIndex = 0;
66      private Object next = null;
67  
68      public boolean hasMoreElements() {
69        try {
70          synchronized (results) {
71            if (next != null)
72              return true;
73  
74            while (nextResultIndex >= results.size()) {
75              if (runningThreads <= 0)
76                return false;
77              results.wait();
78            }
79  
80            next = results.elementAt(nextResultIndex++);
81            return true;
82          }
83        } catch (InterruptedException e) {
84          return false;
85        }
86      }
87  
88      public Object nextElement() {
89        synchronized (results) {
90          if (hasMoreElements()) {
91            Object it = next;
92            next = null;
93            return it;
94          } else
95            throw new NoSuchElementException("No more search hits");
96        }
97      }
98    }
99  
100   public Metasearch(
101     Bookshop[] shopsP,
102     String title,
103     String author,
104     ToTidyList toTidy) {
105     this.shops = shopsP;
106     this.title = title;
107     this.author = author;
108     this.toTidy = toTidy;
109 
110     threads = new SearchThread[shops.length];
111     if (toTidy != null)
112       toTidy.add(this);
113 
114     for (int s = 0; s < shops.length; ++s) {
115       (threads[s] = new SearchThread(shops[s])).start();
116       synchronized (results) {
117         ++runningThreads;
118       }
119     }
120   }
121 
122   public Enumeration currentAndFutureResults() {
123     return new HitsEnumeration();
124   }
125 
126   public Vector currentResults() {
127     return results;
128   }
129 
130   public boolean running() {
131     return runningThreads > 0;
132   }
133 
134   public void close() {
135     try {
136       for (int i = 0; i < threads.length; ++i)
137         try {
138           threads[i].stop();
139         } catch (Exception e) {
140         }
141     } finally {
142       synchronized (this) {
143         runningThreads = 0;
144         notifyAll();
145       }
146     }
147   }
148 
149   protected void finalize() throws Throwable {
150     close();
151   }
152 }