Cleanup rercounts
[yaz4j-moved-to-github.git] / src / main / java / org / yaz4j / Connection.java
1 package org.yaz4j;
2
3 import org.yaz4j.exception.ZoomImplementationException;
4 import org.yaz4j.exception.ConnectionTimeoutException;
5 import org.yaz4j.exception.InitRejectedException;
6 import org.yaz4j.exception.Bib1Exception;
7 import org.yaz4j.exception.InvalidQueryException;
8 import org.yaz4j.exception.Bib1Diagnostic;
9 import org.yaz4j.exception.ConnectionUnavailableException;
10 import org.yaz4j.exception.ZoomException;
11 import org.yaz4j.jni.SWIGTYPE_p_ZOOM_connection_p;
12 import org.yaz4j.jni.SWIGTYPE_p_ZOOM_query_p;
13 import org.yaz4j.jni.SWIGTYPE_p_ZOOM_resultset_p;
14 import org.yaz4j.jni.SWIGTYPE_p_ZOOM_scanset_p;
15 import org.yaz4j.jni.SWIGTYPE_p_ZOOM_options_p;
16 import org.yaz4j.jni.yaz4jlib;
17 import org.yaz4j.jni.yaz4jlibConstants;
18
19 public class Connection {
20     private String host;
21     private int port;
22     final private SWIGTYPE_p_ZOOM_options_p options;
23     protected SWIGTYPE_p_ZOOM_connection_p zoomConnection;
24     //connection is initially closed
25     protected boolean closed = true;
26     private boolean disposed = false;
27
28     public enum QueryType {
29         CQLQuery, PrefixQuery
30     };
31
32     static {
33         // on Linux   'yaz4j' maps to 'libyaz4j.so' (i.e. 'lib' prefix & '.so'  extension)
34         // on Windows 'yaz4j' maps to 'yaz4j.dll'   (i.e.                '.dll' extension)
35         String libName = "yaz4j";
36         try {
37             // System.err.println( "Loading library '"+ System.mapLibraryName( libName ) + "'" );
38             System.loadLibrary(libName);
39         } catch (AbstractMethodError e) {
40             System.err.println("Fatal Error: Failed to load library '" + System.mapLibraryName(libName) + "'");
41             e.printStackTrace();
42         }
43     }
44
45     public Connection(String host, int port) {
46         this.host = host;
47         this.port = port;
48         options = yaz4jlib.ZOOM_options_create();
49     }
50
51     public void finalize() {
52         _dispose();
53     }
54
55     public ResultSet search(String query, QueryType queryType) throws ZoomException {
56       if (closed) throw new IllegalStateException("Connection is closed.");
57         SWIGTYPE_p_ZOOM_query_p yazQuery = yaz4jlib.ZOOM_query_create();
58         ResultSet resultSet = null;
59
60         try {
61             if (queryType == QueryType.CQLQuery) {
62                 yaz4jlib.ZOOM_query_cql(yazQuery, query);
63             } else if (queryType == QueryType.PrefixQuery) {
64                 yaz4jlib.ZOOM_query_prefix(yazQuery, query);
65             } else {
66                 throw new InvalidQueryException("queryType");
67             }
68
69             SWIGTYPE_p_ZOOM_resultset_p yazResultSet = yaz4jlib.ZOOM_connection_search(zoomConnection, yazQuery);
70
71             int errorCode = yaz4jlib.ZOOM_connection_errcode(zoomConnection);
72             if (errorCode != yaz4jlib.ZOOM_ERROR_NONE) {
73                 yaz4jlib.ZOOM_resultset_destroy(yazResultSet);
74             }
75             checkErrorCodeAndThrow(errorCode);
76
77             resultSet = new ResultSet(yazResultSet, this);
78         } finally {
79             yaz4jlib.ZOOM_query_destroy(yazQuery); // deallocate yazQuery also when exceptions
80             yazQuery = null;
81         }
82         return resultSet;
83     }
84
85     public ScanSet scan(String query) throws ZoomException {
86       if (closed) throw new IllegalStateException("Connection is closed.");
87         SWIGTYPE_p_ZOOM_scanset_p yazScanSet = yaz4jlib.ZOOM_connection_scan(zoomConnection, query);
88
89         int errorCode = yaz4jlib.ZOOM_connection_errcode(zoomConnection);
90         if (errorCode != yaz4jlib.ZOOM_ERROR_NONE) {
91             yaz4jlib.ZOOM_scanset_destroy(yazScanSet);
92         }
93         checkErrorCodeAndThrow(errorCode);
94
95         ScanSet scanSet = new ScanSet(yazScanSet, this);
96         return scanSet;
97     }
98
99     /**
100      * Initiates the connection
101      */
102     public void connect() throws ZoomException {
103       //this is temporary before ZOOM-C has proper close method, right now
104       // simply recreate connection
105       if (closed)
106         zoomConnection = yaz4jlib.ZOOM_connection_create(options);
107       yaz4jlib.ZOOM_connection_connect(zoomConnection, host, port);
108       int errorCode = yaz4jlib.ZOOM_connection_errcode(zoomConnection);
109       checkErrorCodeAndThrow(errorCode);
110       closed = false;
111     }
112
113     /**
114      * Closes the connection.
115      */
116     public void close() {
117       if (!closed) {
118         yaz4jlib.ZOOM_connection_destroy(zoomConnection);
119         zoomConnection = null;
120         closed = true;
121       }
122     }
123
124     private void checkErrorCodeAndThrow(int errorCode) throws ZoomException {
125         String message;
126
127         if (errorCode == yaz4jlibConstants.ZOOM_ERROR_NONE) {
128             return;
129         } else if (errorCode == yaz4jlib.ZOOM_ERROR_CONNECT) {
130             message = String.format("Connection could not be made to %s:%d", host, port);
131             throw new ConnectionUnavailableException(message);
132         } else if (errorCode == yaz4jlib.ZOOM_ERROR_INVALID_QUERY) {
133             message = String.format("The query requested is not valid or not supported");
134             throw new InvalidQueryException(message);
135         } else if (errorCode == yaz4jlib.ZOOM_ERROR_INIT) {
136             message = String.format("Server %s:%d rejected our init request", host, port);
137             throw new InitRejectedException(message);
138         } else if (errorCode == yaz4jlib.ZOOM_ERROR_TIMEOUT) {
139             message = String.format("Server %s:%d timed out handling our request", host, port);
140             throw new ConnectionTimeoutException(message);
141         } else if ((errorCode == yaz4jlib.ZOOM_ERROR_MEMORY) || (errorCode == yaz4jlib.ZOOM_ERROR_ENCODE) || (errorCode == yaz4jlib.ZOOM_ERROR_DECODE) || (errorCode == yaz4jlib.ZOOM_ERROR_CONNECTION_LOST) || (errorCode == yaz4jlib.ZOOM_ERROR_INTERNAL) || (errorCode == yaz4jlib.ZOOM_ERROR_UNSUPPORTED_PROTOCOL) || (errorCode == yaz4jlib.ZOOM_ERROR_UNSUPPORTED_QUERY)) {
142             message = yaz4jlib.ZOOM_connection_errmsg(zoomConnection);
143             throw new ZoomImplementationException("A fatal error occurred in Yaz: " + errorCode + " - " + message);
144         } else {
145             String errMsgBib1 = "Bib1Exception: Error Code = " + errorCode + " (" + Bib1Diagnostic.getError(errorCode) + ")";
146             throw new Bib1Exception(errMsgBib1);
147         }
148     }
149
150     /**
151      * Write option with a given name.
152      * @param name option name
153      * @param value option value
154      * @return connection (self) for chainability
155      */
156     public Connection option(String name, String value) {
157       yaz4jlib.ZOOM_options_set(options, name, value);
158       return this;
159     }
160
161     /**
162      * Read option with a given name
163      * @param name option name
164      * @return option value
165      */
166     public String option(String name) {
167       return yaz4jlib.ZOOM_options_get(options, name);
168     }
169
170     public String getSyntax() {
171         return option("preferredRecordSyntax");
172     }
173
174     public void setSyntax(String value) {
175         option("preferredRecordSyntax", value);
176     }
177
178     public String getDatabaseName() {
179         return option("databaseName");
180     }
181
182     public void setDatabaseName(String value) {
183         option("databaseName", value);
184     }
185
186     public String getUsername() {
187         return option("user");
188     }
189
190     public void setUsername(String value) {
191         option("user", value);
192     }
193
194     public String getPassword() {
195         return option("password");
196     }
197
198     public void setPassword(String value) {
199         option("password", value);
200     }
201
202     /**
203      * INTERNAL, GC-ONLY
204      */
205     void _dispose() {
206         if (!disposed) {
207           close();
208           disposed = true;
209         }
210     }
211 }