Fix error handling in ResultSet#getRecords
[yaz4j-moved-to-github.git] / src / main / java / org / yaz4j / Connection.java
1 package org.yaz4j;
2
3 import org.yaz4j.exception.ZoomException;
4 import org.yaz4j.jni.SWIGTYPE_p_ZOOM_connection_p;
5 import org.yaz4j.jni.SWIGTYPE_p_ZOOM_query_p;
6 import org.yaz4j.jni.SWIGTYPE_p_ZOOM_resultset_p;
7 import org.yaz4j.jni.SWIGTYPE_p_ZOOM_scanset_p;
8 import org.yaz4j.jni.yaz4jlib;
9
10 /**
11  * Class representing an on-going communication with an IR server.
12  *
13  * Creating an instance of this class does not automatically connect (e.g open
14  * a socket) to the remote server as the programmer may want to specify options
15  * on the object before establishing the actual connection.
16  *
17  * The work-flow for synchronous (the only addressed) operation when using this
18  * class should be as follows (in pseudocode):
19  *
20  * <blockquote><pre>
21  *
22  * try {
23  *  c = new Connection(...)
24  *  //possibly set some options
25  *  c.connect //establishes connection
26  *  c.search //or other operation
27  *  //possibly retrieve records
28  * catch (ZoomException e) {
29  *  //handle any protocol- or network-level errors
30  * } finally {
31  *  c.close //close the socket
32  * }
33  *
34  * </pre></blockquote>
35  * @see <a href="http://www.indexdata.com/yaz/doc/zoom.html#zoom-connections">YAZ ZOOM Connection</a>
36  * @author jakub
37  */
38 public class Connection {
39
40   private String host;
41   private int port;
42   protected SWIGTYPE_p_ZOOM_connection_p zoomConnection;
43   //connection is initially closed
44   protected boolean closed = true;
45   private boolean disposed = false;
46
47   public enum QueryType {
48
49     CQLQuery, PrefixQuery
50   };
51
52   static {
53     // on Linux   'yaz4j' maps to 'libyaz4j.so' (i.e. 'lib' prefix & '.so'  extension)
54     // on Windows 'yaz4j' maps to 'yaz4j.dll'   (i.e.                '.dll' extension)
55     String libName = "yaz4j";
56     System.loadLibrary(libName);
57   }
58
59   /**
60    * Create new connection object without physically opening a connection to the
61    * remote server.
62    * @param host host name of the server
63    * @param port port of the server
64    */
65   public Connection(String host, int port) {
66     this.host = host;
67     this.port = port;
68     zoomConnection = yaz4jlib.ZOOM_connection_create(null);
69   }
70
71   public void finalize() {
72     _dispose();
73   }
74
75   /**
76    * Performs a search operation (submits the query to the server, waits for
77    * response and creates a new result set that allows to retrieve particular
78    * results)
79    * @deprecated Does not allow specifying sort criteria prior to search
80    * use {@link #search(org.yaz4j.Query) search(Query)} instead.
81    * @param query search query
82    * @param queryType type of the query (e.g RPN. CQL)
83    * @return result set containing records (hits)
84    * @throws ZoomException protocol or network-level error
85    */
86   @Deprecated
87   public ResultSet search(String query, QueryType queryType) throws
88     ZoomException {
89     if (closed) {
90       throw new IllegalStateException("Connection is closed.");
91     }
92     SWIGTYPE_p_ZOOM_query_p yazQuery = null;
93     if (queryType == QueryType.CQLQuery) {
94       yazQuery = yaz4jlib.ZOOM_query_create();
95       yaz4jlib.ZOOM_query_cql(yazQuery, query);
96     } else if (queryType == QueryType.PrefixQuery) {
97       yazQuery = yaz4jlib.ZOOM_query_create();
98       yaz4jlib.ZOOM_query_prefix(yazQuery, query);
99     }
100     SWIGTYPE_p_ZOOM_resultset_p yazResultSet = yaz4jlib.ZOOM_connection_search(
101       zoomConnection, yazQuery);
102     yaz4jlib.ZOOM_query_destroy(yazQuery);
103     ZoomException err = ExceptionUtil.getError(zoomConnection, host,
104       port);
105     if (err != null) {
106       yaz4jlib.ZOOM_resultset_destroy(yazResultSet);
107       throw err;
108     }
109     return new ResultSet(yazResultSet, this);
110   }
111   
112     /**
113    * Performs a search operation (submits the query to the server, waits for
114    * response and creates a new result set that allows to retrieve particular
115    * results). Sort criteria may be specified prior to the search, directly
116    * on the query object.
117    * @param query search query of any type supported by YAZ.
118    * @return result set containing records (hits)
119    * @throws ZoomException protocol or network-level error
120    */
121   public ResultSet search(Query query) throws ZoomException {
122     if (closed) {
123       throw new IllegalStateException("Connection is closed.");
124     }
125     SWIGTYPE_p_ZOOM_resultset_p yazResultSet = yaz4jlib.ZOOM_connection_search(
126       zoomConnection, query.query);
127     ZoomException err = ExceptionUtil.getError(zoomConnection, host,
128       port);
129     if (err != null) {
130       yaz4jlib.ZOOM_resultset_destroy(yazResultSet);
131       throw err;
132     }
133     return new ResultSet(yazResultSet, this);
134   }
135
136   /**
137    * Performs a scan operation (obtains a list of candidate search terms against
138    * a particular access point). 
139    * @deprecated Only allows PQF scan queries, use {@link #scan(org.yaz4j.Query) scan(Query)} instead
140    * @param query query for scanning
141    * @return a scan set with the terms
142    * @throws ZoomException a protocol or network-level error
143    */
144   @Deprecated
145   public ScanSet scan(String query) throws ZoomException {
146     if (closed) {
147       throw new IllegalStateException("Connection is closed.");
148     }
149     SWIGTYPE_p_ZOOM_scanset_p yazScanSet = yaz4jlib.ZOOM_connection_scan(
150       zoomConnection, query);
151     ZoomException err = ExceptionUtil.getError(zoomConnection, host, port);
152     if (err != null) {
153       yaz4jlib.ZOOM_scanset_destroy(yazScanSet);
154       throw err;
155     }
156     ScanSet scanSet = new ScanSet(yazScanSet, this);
157     return scanSet;
158   }
159   
160     /**
161    * Performs a scan operation (obtains a list of candidate search terms against
162    * a particular access point). Allows to use both CQL and PQF for Scan.
163    * @see <a href="http://www.indexdata.com/yaz/doc/zoom.scan.html">ZOOM-API Scan</a>
164    * @param query scan query of type supported by YAZ
165    * @return a scan set with the terms
166    * @throws ZoomException a protocol or network-level error
167    */
168   public ScanSet scan(Query query) throws ZoomException {
169     if (closed) {
170       throw new IllegalStateException("Connection is closed.");
171     }
172     SWIGTYPE_p_ZOOM_scanset_p yazScanSet = yaz4jlib.ZOOM_connection_scan1(
173       zoomConnection, query.query);
174     ZoomException err = ExceptionUtil.getError(zoomConnection, host, port);
175     if (err != null) {
176       yaz4jlib.ZOOM_scanset_destroy(yazScanSet);
177       throw err;
178     }
179     ScanSet scanSet = new ScanSet(yazScanSet, this);
180     return scanSet;
181   }
182
183   /**
184    * Establishes a connection to the remote server.
185    * @throws ZoomException any (possibly network-level) errors that may occurr
186    */
187   public void connect() throws ZoomException {
188     yaz4jlib.ZOOM_connection_connect(zoomConnection, host, port);
189     ZoomException err = ExceptionUtil.getError(zoomConnection, host, port);
190     if (err != null) {
191       throw err;
192     }
193     closed = false;
194   }
195
196   /**
197    * Closes the connection.
198    */
199   public void close() {
200     yaz4jlib.ZOOM_connection_close(zoomConnection);
201     closed = true;
202   }
203   
204   /**
205    * Return exception type from current connection
206    *
207    * @return null if no error
208    */
209   ZoomException getZoomException() {
210     ZoomException err = ExceptionUtil.getError(zoomConnection, host, port);
211     return err;
212   }
213
214   /**
215    * Write option with a given name.
216    * @param name option name
217    * @param value option value
218    * @return connection (self) for chainability
219    */
220   public Connection option(String name, String value) {
221     yaz4jlib.ZOOM_connection_option_set(zoomConnection, name, value);
222     return this;
223   }
224
225   /**
226    * Read option with a given name
227    * @param name option name
228    * @return option value
229    */
230   public String option(String name) {
231     return yaz4jlib.ZOOM_connection_option_get(zoomConnection, name);
232   }
233
234   /**
235    * Same as option("preferredRecordSyntax")
236    * @return value of preferred record syntax
237    */
238   public String getSyntax() {
239     return option("preferredRecordSyntax");
240   }
241
242   /**
243    * Same as option("preferredRecordSyntax", value)
244    * @param value value of preferred record syntax
245    */
246   public void setSyntax(String value) {
247     option("preferredRecordSyntax", value);
248   }
249
250   /**
251    * Same as option("databaseName")
252    * @return value of databaseName
253    */
254   public String getDatabaseName() {
255     return option("databaseName");
256   }
257
258   /**
259    * Same as option("databaseName", value)
260    * @param value value of databaseName
261    */
262   public void setDatabaseName(String value) {
263     option("databaseName", value);
264   }
265
266   /**
267    * Same as option("user")
268    * @return value of user
269    */
270   public String getUsername() {
271     return option("user");
272   }
273
274   /**
275    * Same as option("user", value)
276    * @param value value of user
277    */
278   public void setUsername(String value) {
279     option("user", value);
280   }
281
282   /**
283    * Same as option("password")
284    * @return value of password
285    */
286   public String getPassword() {
287     return option("password");
288   }
289
290   /**
291    * Same as option("password", value)
292    * @param value
293    */
294   public void setPassword(String value) {
295     option("password", value);
296   }
297
298   /**
299    * INTERNAL, GC-ONLY
300    */
301   void _dispose() {
302     if (!disposed) {
303       yaz4jlib.ZOOM_connection_destroy(zoomConnection);
304       zoomConnection = null;
305       disposed = true;
306     }
307   }
308 }