use IsisDB module instead of OpenIsis -- this will fix various problems in
[webpac] / openisis / org / openisis / NativeDb.java
1 /*
2         openisis - an open implementation of the CDS/ISIS database
3         Version 0.8.x (patchlevel see file Version)
4         Copyright (C) 2001-2003 by Erik Grziwotz, erik@openisis.org
5
6         This library is free software; you can redistribute it and/or
7         modify it under the terms of the GNU Lesser General Public
8         License as published by the Free Software Foundation; either
9         version 2.1 of the License, or (at your option) any later version.
10
11         This library is distributed in the hope that it will be useful,
12         but WITHOUT ANY WARRANTY; without even the implied warranty of
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14         Lesser General Public License for more details.
15
16         You should have received a copy of the GNU Lesser General Public
17         License along with this library; if not, write to the Free Software
18         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20         see README for more information
21 EOH */
22
23 package org.openisis;
24
25 import java.io.IOException;
26 import java.io.FileNotFoundException;
27 import java.io.UnsupportedEncodingException;
28 import java.util.Iterator;
29 import java.util.NoSuchElementException;
30
31
32 /**
33         This class is the native implementation of class Db.
34 <h3>Installation</h3>
35         The shared library "openjsis" must be loadable.
36         On a UNIX System, make sure that the file libopenjsis.so
37         resides in a directory listed by the environment variable
38         LD_LIBRARY_PATH or in /etc/ld.so.conf. 
39         If you just drop it in /usr/lib or similar dir,
40         you may have to run a command like ldconfig.
41 <p>
42         On Windows, put openjsis.dll somewhere in the PATH.
43 <p>
44         $Id: NativeDb.java,v 1.5 2003/04/08 00:20:53 kripke Exp $
45         @version $Revision: 1.5 $
46         @author  $Author: kripke $
47 */
48 public class NativeDb extends Db {
49
50         private static synchronized native
51         short nopen ( String dbname, String[] args );
52
53         /** read a record by rowid.
54          *      The native implementation gives character data as byte[],
55          *      since we need to employ java encoding mechanisms anyway.
56          *      The tag is packed as four bytes little endian.
57          *      @param db a db number as returned by open
58          *      @param rowid the number (aka mfn) of the row
59          *      @param tag in which to look for txt, negative for any
60          *      @param txt to grep from record, null for no grep
61          *      @return an array of Objects:
62          *              the first is an array of ints filled with rowid an tags
63          *              the others are byte[] with field character data in encoding
64          *      @see #encoding
65         */
66         private static synchronized native
67         Object[] nreadRow ( short db, int rowid, int tag, byte[] txt );
68
69         /** search for terms */
70         private static synchronized native
71         Object[] nTerms ( short db, byte[] term, byte[] start );
72
73         /** get matching rowids */
74         private static synchronized native
75         int[] nsearch ( short db, byte[] key, int mode );
76
77         /** plain write */
78         private static synchronized native
79         short nwriteRow ( short db, Object[] data );
80
81         /** 
82          * Indexed write
83          * @param db database handle returned by open
84          * @param data an Object array with an int[] on idx 0 containing
85          * rowid and tags and with byte[] containing appropriate data for
86          * the tags; thus a simple sanity check for a properly structured 
87          * data is: data.length == data[ 0 ].length
88          * @param idx same as data but contains a record that holds index
89          * information
90          */
91         private static synchronized native
92         short nwriteXRow ( short db, Object[] data, Object[] idx );
93
94         static {
95                 // TODO: try some explicit paths like our jar's location with System.load
96                 // in order to not have to export LD_LIBRARY_PATH or so
97                 System.loadLibrary( "openjsis" );
98         }
99
100         public byte[] cvt ( String txt ) {
101                 try {
102                         return txt.getBytes(encoding);
103                 } catch ( UnsupportedEncodingException e ) {
104                         // shouldn't happen -- our fault
105                         throw new Error( "failed to check for support of encoding "+encoding );
106                 }
107         }
108
109         public String cvt ( byte[] b ) {
110                 try {
111                         // System.err.println( "got "+b.length+" bytes "+b );
112                         for ( int l=b.length; 0<l; l-- ) {
113                                 String s = new String( b, 0, l, encoding );
114                                 if ( null != s && 0 != s.length() )
115                                         return s;
116                                 for ( int i=0; i<l; i++ )
117                                         System.err.print(
118                                                 (
119                                                 b[i] > 0 ? "0" : // 0... self-contained
120                                                 b[i] < -64 ? "f" : // 10... six follower bits
121                                                 b[i] < -32 ? "1" : // 110... five bits, one follower
122                                                 b[i] < -16 ? "2" : // 1110... four bits, two followers
123                                                 "b" // bad
124                                                 ) + "("+b[i]+")"
125                                         );
126                                 return "";
127                         }
128                         return "";
129                 } catch ( UnsupportedEncodingException e ) {
130                         // shouldn't happen -- our fault
131                         throw new Error( "failed to check for support of encoding "+encoding );
132                 }
133         }
134
135
136         /** Number of this db.
137         */
138         public final short db;
139         
140
141         public NativeDb ( String enc, String dbname, String[] args )
142                 throws IOException
143         {
144                 super( enc );
145                 db = nopen( dbname, args );
146                 if ( 0 > db )
147                         throw new FileNotFoundException();
148         }
149
150         Rec mkRow ( Object[] buf ) {
151                 if ( null == buf )
152                         return null;
153                 int[] ids = (int[])buf[0];
154                 int rowid = ids[0];
155                 Field[] f = new Field[ buf.length-1 ];
156                 for ( int i=1; i<buf.length; i++ )
157                         f[i-1] = new Field( ids[i], cvt( (byte[])buf[i] ) );
158                 return new Rec( rowid, f );
159         }       // readrow
160
161         Object[] mkBuf ( Rec rec ) {
162                 if ( null == rec )
163                         return null;
164                 int len = rec.getLen() + 1;
165                 Object[] buf = new Object[ len ];
166                 int[] tags = new int[ len ];
167                 for ( int i = 1; i < len; i++ ) {
168                         Field f = rec.getField( i - 1 );
169                         tags[ i ] = f.tag;
170                         buf[ i ] = cvt( f.val );
171                         String tttt = new String( cvt( f.val ) );
172                         System.out.println( "field [ " + i + "] = " + tttt + " len is " + tttt.length() );
173                 }
174                 tags[ 0 ] = rec.getRowId();
175                 buf[ 0 ] = tags;
176                 return buf;
177         }
178
179         public Rec readRow ( int rowid ) {
180                 return mkRow( nreadRow( db, rowid, -1, null ) );
181         }
182
183         public short writeRow ( Rec rec ) {
184                 return nwriteRow( db, mkBuf( rec ) ); 
185         }
186
187         public short writeXRow ( Rec rec, Rec idx ) {
188                 return nwriteXRow( db, mkBuf( rec ), mkBuf( idx ) ); 
189         }
190
191         public Rec scanRow ( int rowid, int tag, String txt ) {
192                 return mkRow( nreadRow( db, rowid, tag, cvt(txt) ) );
193         }
194
195         public int[] search ( String key, int mode ) {
196                 return nsearch( db, cvt(key), mode );
197         }
198
199         public class TermIterator implements Iterator {
200                 byte[] _prefix;
201                 Object[] buf;
202                 int nxt;
203
204                 public TermIterator ( String prefix ) {
205                         _prefix = cvt(prefix+"$");
206                 }
207
208                 public boolean hasNext () {
209                         if ( null != buf && nxt < buf.length ) return true;
210                         if ( nxt < 0 ) return false;
211                         nxt = -1; // mark, just in case we bomb
212                         buf = nTerms( db, _prefix,
213                                 null == buf ? null : (byte[])buf[buf.length-1] );
214                         if ( null == buf || 1 >= buf.length ) {
215                                 buf = null;
216                                 return false;
217                         }
218                         nxt = 1;
219                         return true;
220                 }
221
222                 public Object next () {
223                         if ( ! hasNext() ) throw new NoSuchElementException();
224                         return cvt( (byte[])buf[nxt++] );
225                 }
226
227                 public void remove () { throw new UnsupportedOperationException(); }
228
229         }
230
231         public Iterator terms ( String prefix ) {
232                 return new TermIterator( prefix );
233         }
234
235 }       // NativeDb