KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sqlmagic > tinysql > textFileTable


1 /*
2  * Extension of tinySQLTable which manipulates text files.
3  *
4  * Copyright 1996, Brian C. Jepson
5  * (bjepson@ids.net)
6  *
7  * $Author: davis $
8  * $Date: 2004/12/18 21:26:34 $
9  * $Revision: 1.1 $
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24  *
25  */

26
27 package com.sqlmagic.tinysql;
28
29 import java.util.*;
30 import java.lang.*;
31 import java.io.*;
32 import java.sql.Types JavaDoc;
33
34 /**
35  * @author Thomas Morgner <mgs@sherito.org> Changed column types to java.sql.types.
36  */

37 public class textFileTable extends tinySQLTable {
38
39   // The data directory for tables
40
//
41
public String JavaDoc dataDir;
42
43   // the object I'll use to manipulate the table
44
//
45
RandomAccessFile ftbl;
46
47   // some constants that I don't actually use that much...
48
//
49
int COLUMN_SIZE = 0;
50   int COLUMN_TYPE = 1;
51   int COLUMN_POS = 2;
52
53   long record_number = 0; // current record
54
long record_length; // length of a record
55

56   /**
57    *
58    * Constructs a textFileTable. This is only called by getTable()
59    * in textFile.java.
60    *
61    * @param dDir data directory
62    * @param table_name the name of the table
63    *
64    */

65   textFileTable( String JavaDoc dDir, String JavaDoc table_name ) throws tinySQLException {
66
67     dataDir = dDir; // set the data directory
68
table = table_name; // set the table name
69

70     // attempt to open the file in read/write mode
71
//
72
try {
73       ftbl = new RandomAccessFile(dataDir + "/" + table_name, "rw");
74     } catch (Exception JavaDoc e) {
75       throw new tinySQLException("Could not open the file " + table + ".");
76     }
77
78     // read in the table definition
79
//
80
readColumnInfo();
81
82   }
83   public int GetRowCount() {
84     // Not implemented get for text files.
85
return 0;
86   }
87   /**
88   @return Length in bytes of one row
89   or 0 if not known
90   */

91   public int getRecordLength() {
92     return 0;
93   }
94
95
96   /**
97    *
98    * close method. Try not to call this until you are sure
99    * the object is about to go out of scope.
100    *
101    */

102   public void close() throws tinySQLException {
103
104     try {
105       ftbl.close();
106     } catch (IOException e) {
107       throw new tinySQLException(e.getMessage());
108     }
109   }
110   /**
111    *
112    * Check if file is open for writing.
113    *
114    */

115   public boolean isOpen() throws tinySQLException {
116
117     return true;
118   }
119
120   /**
121    *
122    * Returns the size of a column
123    *
124    * @param column name of the column
125    * @see tinySQLTable#ColSize
126    *
127    */

128   public int ColSize(String JavaDoc column) {
129
130     // retrieve the column info array from the column_info Hashtable
131
//
132
String JavaDoc info[] = (String JavaDoc[]) column_info.get(column);
133
134     // return its size
135
//
136
return Integer.parseInt( info[COLUMN_SIZE] );
137
138   }
139   public int ColDec(String JavaDoc column) {
140     // returns the decimal places for a column - not implemented
141
// for text files.
142
return 0;
143   }
144
145
146   /**
147    *
148    * Returns the datatype of a column.
149    *
150    * @param column name of the column.
151    * @see tinySQLTable#ColType
152    *
153    * @author Thomas Morgner <mgs@sherito.org>
154    * Q&D Hack, Just assume everybody uses java.sql.Types-IntegerConstants
155    * as Type Declaration. Perhaps there could be an translation function,
156    * which converts Strings to Integer-Types.
157    */

158   public int ColType(String JavaDoc column) {
159
160     // retrieve the column info array from the column_info Hashtable
161
//
162
String JavaDoc info[] = (String JavaDoc[]) column_info.get(column);
163
164     // return its datatype
165
//
166
return Integer.parseInt(info[COLUMN_TYPE]);
167
168   }
169
170   /**
171    *
172    * Updates the current row in the table.
173    *
174    * @param c Ordered Vector of column names
175    * @param v Ordered Vector (must match order of c) of values
176    * @see tinySQLTable#UpdateCurrentRow
177    *
178    */

179   public void UpdateCurrentRow(Vector c, Vector v) throws tinySQLException {
180
181     // the Vectors v and c are expected to have the
182
// same number of elements. It is also expected
183
// that the elements correspond to each other,
184
// such that value 1 of Vector v corresponds to
185
// column 1 of Vector c, and so forth.
186
//
187
for (int i = 0; i < v.size(); i++) {
188
189        // get the column name and the value, and
190
// invoke UpdateCol() to update it.
191
//
192
String JavaDoc column = (String JavaDoc) c.elementAt(i);
193        String JavaDoc value = (String JavaDoc) v.elementAt(i);
194        UpdateCol(column, value);
195     }
196
197   }
198
199   /**
200    *
201    * Position the record pointer at the top of the table.
202    *
203    * @see tinySQLTable#GoTop
204    *
205    */

206   public void GoTop() throws tinySQLException {
207
208     try {
209       ftbl.seek(0);
210       record_number = 0;
211     } catch (IOException e) {
212       throw new tinySQLException(e.getMessage());
213     }
214
215   }
216
217   /**
218    *
219    * Advance the record pointer to the next record.
220    *
221    * @see tinySQLTable#NextRecord
222    *
223    */

224   public boolean NextRecord() throws tinySQLException {
225
226     // if the record number is greater than zero,
227
// advance the pointer. Otherwise, we're on the first
228
// record, and it hasn't been visited before.
229
//
230
if (record_number > 0) {
231
232       // try to make it to the next record. An IOException
233
// indicates that we have hit the end of file.
234
//
235
try {
236         ftbl.seek( ftbl.getFilePointer() + record_length + 1);
237       } catch (IOException e) {
238         return false;
239       }
240
241     }
242
243     // increment the record pointer
244
//
245
record_number++;
246
247     // check for end of file, just in case...
248
//
249
try {
250       if (ftbl.getFilePointer() == ftbl.length()) {
251         return false;
252       }
253     } catch (Exception JavaDoc e) {
254       throw new tinySQLException(e.getMessage());
255     }
256
257     return true;
258
259   }
260
261   /**
262    *
263    * Insert a row. If c or v == null, insert a blank row
264    *
265    * @param c Ordered Vector of column names
266    * @param v Ordered Vector (must match order of c) of values
267    * @see tinySQLTable#InsertRow()
268    *
269    */

270   public void InsertRow(Vector c, Vector v) throws tinySQLException {
271
272     try {
273
274       // go to the end of the file
275
//
276
ftbl.seek( ftbl.length() );
277
278       // write out the deleted indicator
279
//
280
ftbl.write('N');
281
282       // write out a blank record
283
//
284
for (int i = 1; i < record_length; i++) {
285         ftbl.write(' ');
286       }
287       ftbl.write('\n');
288
289       // reposition at start of current record
290
//
291
ftbl.seek( ftbl.getFilePointer() - (record_length + 1) );
292
293     } catch (Exception JavaDoc e) {
294       throw new tinySQLException(e.getMessage());
295     }
296
297     if (c != null && v != null)
298       UpdateCurrentRow(c, v);
299   }
300
301   /**
302    *
303    * Retrieve a column's string value from the current row.
304    *
305    * @param column the column name
306    * @see tinySQLTable#GetCol
307    *
308    */

309   public String JavaDoc GetCol(String JavaDoc column) throws tinySQLException {
310
311     try {
312
313       // get the column info
314
//
315
String JavaDoc info[] = (String JavaDoc[]) column_info.get(column);
316
317       // retrieve datatype, size, and position within row
318
//
319
String JavaDoc datatype = info[COLUMN_TYPE];
320       int size = Integer.parseInt(info[COLUMN_SIZE]);
321       int pos = Integer.parseInt(info[COLUMN_POS]);
322
323       // save the file pointer
324
//
325
long OldPosition = ftbl.getFilePointer();
326
327       // read the whole line from this row.
328
//
329
String JavaDoc line = ftbl.readLine();
330
331       // retrieve the column from the line we just read,
332
// at offset pos, for length size
333
//
334
String JavaDoc result = line.substring(pos, pos + size);
335
336       // restore the file pointer
337
//
338
ftbl.seek( OldPosition );
339
340       // trim the result if it was numeric
341
//
342
if (datatype.equals("NUMERIC")) {
343         return result.trim();
344       } else {
345         return result;
346       }
347
348     } catch (Exception JavaDoc e) {
349       throw new tinySQLException(e.getMessage());
350     }
351   }
352
353   /**
354    *
355    * Update a single column.
356    *
357    * @param column the column name
358    * @param value the String value with which update the column
359    * @see tinySQLTable#UpdateCol
360    *
361    */

362   public void UpdateCol( String JavaDoc column, String JavaDoc value ) throws tinySQLException {
363
364     try {
365
366       // read the column info
367
//
368
String JavaDoc info[] = (String JavaDoc[]) column_info.get(column);
369
370       // retrieve datatype, size, and position within row
371
//
372
String JavaDoc datatype = info[COLUMN_TYPE];
373       long size = Long.parseLong(info[COLUMN_SIZE]);
374       long pos = Long.parseLong(info[COLUMN_POS]);
375
376       // position the file pointer at the column
377
// offset.
378
//
379
ftbl.seek( ftbl.getFilePointer() + pos );
380       String JavaDoc writeval;
381
382       if (value.length() > (int) size) {
383
384         // truncate the value, if it exceeds the width
385
// of the column
386
//
387
writeval = value.substring(0, (int) size);
388
389       } else {
390
391         // add some padding to the end of the string
392
//
393
StringBuffer JavaDoc pad = new StringBuffer JavaDoc();
394         for (int p = 0; p < ((int) size) - value.length(); p++) {
395           pad.append(" ");
396         }
397         writeval = value + pad.toString();
398       }
399
400       // write out the column
401
//
402
ftbl.writeBytes(writeval);
403
404       // rewind the file pointer
405
//
406
ftbl.seek( ftbl.getFilePointer() - (pos + (long) writeval.length()) );
407
408     } catch (Exception JavaDoc e) {
409       e.printStackTrace();
410       throw new tinySQLException(e.getMessage());
411     }
412   }
413
414   /**
415    *
416    * Delete the current row.
417    *
418    * @see tinySQLTable#DeleteRow
419    *
420    */

421   public void DeleteRow() throws tinySQLException {
422
423     // this is real easy; just flip the value of the _DELETED column
424
//
425
UpdateCol("_DELETED", "Y");
426
427   }
428
429   /**
430    *
431    * Is the current row deleted?
432    *
433    * @see tinySQLTable#isDeleted()
434    *
435    */

436   public boolean isDeleted() throws tinySQLException {
437
438     // this is real easy; just check the value of the _DELETED column
439
//
440
return (GetCol("_DELETED")).equals("Y");
441   }
442
443   // end methods implemented from tinySQLTable.java
444
// the rest of this stuff is internal methods
445
// for textFileTable
446
//
447

448   /*
449    *
450    * Reads in a table definition and populates the column_info
451    * Hashtable
452    *
453    */

454   void readColumnInfo() throws tinySQLException {
455
456     try {
457
458       column_info = new Hashtable();
459
460       // Open an FileInputStream to the .def (table
461
// definition) file
462
//
463
FileInputStream fdef =
464          new FileInputStream( dataDir + "/" + table + ".def" );
465
466       // use a StreamTokenizer to break up the stream.
467
//
468
Reader r = new BufferedReader(
469         new InputStreamReader(fdef));
470       StreamTokenizer def = new StreamTokenizer (r);
471
472       // set the | as a delimiter, and set everything between
473
// 0 and z as word characters. Let it know that eol is
474
// *not* significant, and that it should parse numbers.
475
//
476
def.whitespaceChars('|', '|');
477       def.wordChars('0', 'z');
478       def.eolIsSignificant(false);
479       def.parseNumbers();
480
481       // read each token from the tokenizer
482
//
483
while ( def.nextToken() != def.TT_EOF ) {
484
485         // first token is the datatype
486
//
487
// Q&D: Default is char value, numeric is special
488
String JavaDoc datatype = String.valueOf (Types.CHAR);
489         if (def.sval.equals ("NUMERIC"))
490         {
491           datatype = String.valueOf (Types.NUMERIC);
492         }
493
494         // get the next token; it's the column name
495
//
496
def.nextToken();
497         String JavaDoc column = def.sval;
498
499         // get the third token; it's the size of the column
500
//
501
def.nextToken();
502         long size = (new Double JavaDoc(def.nval)).longValue();
503
504         // create an info array
505
//
506
String JavaDoc[] info = new String JavaDoc[3];
507
508         // store the datatype, the size, and the position
509
// within the record (the record length *before*
510
// we increment it with the size of this column
511
//
512
info[COLUMN_TYPE] = datatype;
513         info[COLUMN_SIZE] = Long.toString(size);
514         info[COLUMN_POS] = Long.toString(record_length);
515
516         // this is the start position of the next column
517
//
518
record_length += size;
519
520         // store this info in the column_info hash,
521
// keyed by column name.
522
//
523
column_info.put(column, info);
524
525       }
526
527       fdef.close(); // close the file
528

529     } catch (Exception JavaDoc e) {
530
531       throw new tinySQLException(e.getMessage());
532
533     }
534
535   }
536
537 }
538
Popular Tags