/* * Copyright (C) 2005 Laurent Sansonetti * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "rbzoom.h" /* Class: ZOOM::Connection * The Connection object is a session with a target. */ static VALUE cZoomConnection; static VALUE rbz_connection_make (ZOOM_connection connection) { return connection != NULL ? Data_Wrap_Struct (cZoomConnection, NULL, ZOOM_connection_destroy, connection) : Qnil; } static ZOOM_connection rbz_connection_get (VALUE obj) { ZOOM_connection connection; Data_Get_Struct (obj, struct ZOOM_connection_p, connection); assert (connection != NULL); return connection; } #define RAISE_IF_FAILED(connection) \ do { \ int error; \ const char *errmsg; \ const char *addinfo; \ \ error = ZOOM_connection_error (connection, \ &errmsg, \ &addinfo); \ if (error != 0) \ rb_raise (rb_eRuntimeError, "%s (%d) %s", \ errmsg, error, addinfo); \ } \ while (0) /* * Class method: open(host, port=nil) { |conn| ... } * host: hostname of the target to connect to. * port: network port of the target to connect to. * * A convenience method that creates a new connection and attempts to * establish a network connection to the given target, basically calling * ZOOM::Connection.new and ZOOM::Connection#connect. * * If a block is given, then it will be called once the connection is * established, passing a reference to the connection object as a parameter, * and destroying the connection automatically at the end of the block. * With no block, this method just returns the connection object. * * Returns: a newly created ZOOM::Connection object. */ static VALUE rbz_connection_open (int argc, VALUE *argv, VALUE self) { VALUE host; VALUE port; ZOOM_connection connection; VALUE rb_connection; rb_scan_args (argc, argv, "11", &host, &port); connection = ZOOM_connection_new (RVAL2CSTR (host), NIL_P (port) ? 0 : FIX2INT (port)); RAISE_IF_FAILED (connection); rb_connection = rbz_connection_make (connection); if (rb_block_given_p ()) { rb_yield(rb_connection); return Qnil; } return rb_connection; } /* * Class method: new(options=nil) * options: options for the connection, as a Hash object. * * Creates a new connection object, but does not establish a network connection * immediately, allowing you to specify options before (if given). You can * thus establish the connection using ZOOM::Connection#connect. * * Returns: a newly created ZOOM::Connection object. */ static VALUE rbz_connection_new (int argc, VALUE *argv, VALUE self) { ZOOM_options options; ZOOM_connection connection; VALUE rb_options; rb_scan_args (argc, argv, "01", &rb_options); if (NIL_P (rb_options)) options = ZOOM_options_create (); else options = ruby_hash_to_zoom_options (rb_options); connection = ZOOM_connection_create (options); ZOOM_options_destroy (options); RAISE_IF_FAILED (connection); return rbz_connection_make (connection); } /* * Method: connect(host, port=nil) * host: hostname of the target to connect to. * port: network port of the target to connect to. * * Establishes a network connection to the target specified by the given * arguments. If no port is given, 210 will be used. A colon in the host * string denotes the beginning of a port number. If the host string includes * a slash, the following part specifies a database for the connection. * * You can also prefix the host string with a scheme followed by a colon. * The default scheme is tcp (Z39.50 protocol). The scheme http selects SRW * over HTTP. * * This method raises an exception on error. * * Returns: self. */ static VALUE rbz_connection_connect (int argc, VALUE *argv, VALUE self) { ZOOM_connection connection; VALUE host; VALUE port; rb_scan_args (argc, argv, "11", &host, &port); connection = rbz_connection_get (self); ZOOM_connection_connect (connection, RVAL2CSTR (host), NIL_P (port) ? 0 : FIX2INT (port)); RAISE_IF_FAILED (connection); return self; } /* * Method: set_option(key, value) * key: the name of the option, as a string. * value: the value of this option (as a string, integer or boolean). * * Sets an option on the connection. * * Returns: self. */ static VALUE rbz_connection_set_option (VALUE self, VALUE key, VALUE val) { ZOOM_connection connection; connection = rbz_connection_get (self); ZOOM_connection_option_set (connection, RVAL2CSTR (key), RVAL2CSTR (rb_obj_as_string (val))); RAISE_IF_FAILED (connection); return self; } /* * Method: get_option(key) * key: the name of the option, as a string. * * Gets the value of a connection's option. * * Returns: the value of the given option, as a string, integer or boolean. */ static VALUE rbz_connection_get_option (VALUE self, VALUE key) { ZOOM_connection connection; const char *value; connection = rbz_connection_get (self); value = ZOOM_connection_option_get (connection, RVAL2CSTR (key)); RAISE_IF_FAILED (connection); return zoom_option_value_to_ruby_value (value); } /* * Method: search(criterion) * criterion: the search criterion, either as a ZOOM::Query object or as a string, * representing a PQF query. * * Searches the connection from the given criterion. You can either create and * pass a reference to a ZOOM::Query object, or you can simply pass a string * that represents a PQF query. * * This method raises an exception on error. * * Returns: a result set from the search, as a ZOOM::ResultSet object, * empty if no results were found. */ static VALUE rbz_connection_search (VALUE self, VALUE criterion) { ZOOM_connection connection; ZOOM_resultset resultset; connection = rbz_connection_get (self); if (TYPE (criterion) == T_STRING) resultset = ZOOM_connection_search_pqf (connection, RVAL2CSTR (criterion)); else resultset = ZOOM_connection_search (connection, rbz_query_get (criterion)); RAISE_IF_FAILED (connection); assert (resultset != NULL); return rbz_resultset_make (resultset); } void Init_zoom_connection (VALUE mZoom) { VALUE c; c = rb_define_class_under (mZoom, "Connection", rb_cObject); rb_define_singleton_method (c, "open", rbz_connection_open, -1); rb_define_singleton_method (c, "new", rbz_connection_new, -1); rb_define_method (c, "connect", rbz_connection_connect, -1); rb_define_method (c, "set_option", rbz_connection_set_option, 2); rb_define_method (c, "get_option", rbz_connection_get_option, 1); define_zoom_option (c, "implementationName"); define_zoom_option (c, "user"); define_zoom_option (c, "group"); define_zoom_option (c, "password"); define_zoom_option (c, "host"); define_zoom_option (c, "proxy"); define_zoom_option (c, "async"); define_zoom_option (c, "maximumRecordSize"); define_zoom_option (c, "preferredMessageSize"); define_zoom_option (c, "lang"); define_zoom_option (c, "charset"); define_zoom_option (c, "serverImplementationId"); define_zoom_option (c, "targetImplementationName"); define_zoom_option (c, "serverImplementationVersion"); define_zoom_option (c, "databaseName"); define_zoom_option (c, "piggyback"); define_zoom_option (c, "smallSetUpperBound"); define_zoom_option (c, "largeSetLowerBound"); define_zoom_option (c, "mediumSetPresentNumber"); define_zoom_option (c, "smallSetElementSetName"); define_zoom_option (c, "mediumSetElementSetName"); /* herited from Zoom::ResultSet */ define_zoom_option (c, "start"); define_zoom_option (c, "count"); define_zoom_option (c, "presentChunk"); define_zoom_option (c, "elementSetName"); define_zoom_option (c, "preferredRecordSyntax"); define_zoom_option (c, "schema"); define_zoom_option (c, "setname"); rb_define_method (c, "search", rbz_connection_search, 1); cZoomConnection = c; }