-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDataStore.java
421 lines (359 loc) · 9.49 KB
/
DataStore.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
import javafx.util.Pair;
import java.util.ArrayList;
// Abstract Layer for Accessing DataStore
//
public abstract class DataStore {
protected String collectionName = null; // name of the data collection group
protected Schema schema; // the dynamic schema definition for the collection
protected String[] primary = null; // dynamic primary key(s) definition
protected Index index = null; // index of primary key(s)
private Storage storage = null; // data storage
// Constructor
public DataStore( String collectionName )
{
this.collectionName = collectionName;
// Construct the schema object
schema = new Schema( collectionName );
}
// Set Storage Type
public void Storage ( String type )
throws StorageException
{
switch ( type.toLowerCase() ) {
case "single": storage = new SingleFileStorage( collectionName );
break;
case "multi" : storage = new MultiFileStorage( collectionName );
break;
default : throw new StorageException( "Invalid argument for storage type (-t): " + type );
}
}
// Open the storage
public void Open()
throws StorageException
{
if ( null != storage ) {
// open the data store
storage.Open();
// read in the index
ArrayList<long[]> entries = storage.ReadIndex( index );
if ( entries != null ) {
for ( long[] entry : entries ) {
index.Add( entry[ 0 ], entry[ 1 ] );
}
primary = index.Keys(); // update the primary key list
}
// Get the keys from user specified schema (if any)
ArrayList<Pair<String,String>> sKeys = schema.GetKeys();
// No schema has been specified
if ( sKeys == null ) {
// Read in the schema
ArrayList<Pair<String,String>> keys = storage.ReadSchema();
if ( keys != null )
schema.Schema( keys );
}
// Special case for binary store
else if ( this.getClass().getName().equals( "BinaryStore" ) ) {
// Read in the schema
ArrayList<Pair<String,String>> keys = storage.ReadSchema();
// Check if schemas differ
if ( null != keys ) {
if ( keys.size() != sKeys.size() )
throw new StorageException( "Cannot change existing schema when using Binary Store" );
int len = keys.size();
for ( int i = 0; i < len; i++ ) {
if ( !keys.get( i ).getKey().equals( sKeys.get( i ).getKey() ) )
throw new StorageException( "Cannot change existing schema when using Binary Store" );
if ( !keys.get( i ).getValue().equals( sKeys.get( i ).getValue() ) )
throw new StorageException( "Cannot change existing schema when using Binary Store" );
}
}
}
}
}
// Close the storage
public void Close()
throws StorageException
{
if ( null != storage ) {
// close the data store
storage.Close();
// write out the index
storage.Write( index );
// write out the schema
storage.Write( schema );
}
}
// Seek to the begin of the storage
public void Begin()
throws StorageException
{
if ( null != storage )
storage.Begin();
}
// Seek to the end of the storage
public void End()
throws StorageException
{
if ( null != storage )
storage.End();
}
// Seek to a location in the storage
public void Move( long pos )
throws StorageException
{
if ( null != storage )
storage.Move( pos );
}
// Get current position storage
public long Pos()
throws StorageException
{
if ( null != storage )
return storage.Pos();
return -1;
}
// Check if at the end of file
public boolean Eof()
throws StorageException
{
if ( null != storage )
return storage.Eof();
return false;
}
// Write a padded string to storage
public void Write( String value, int length )
throws StorageException
{
if ( null != storage )
storage.Write( value, length );
}
// Write a string
public void Write( String value )
throws StorageException
{
if ( null != storage )
storage.Write( value );
}
// Write a byte
public void Write( byte value )
throws StorageException
{
if ( null != storage )
storage.Write( value );
}
// Write a short to storage
public void Write( short value )
throws StorageException
{
if ( null != storage )
storage.Write( value );
}
// Write an integer to storage
public void Write( int value )
throws StorageException
{
if ( null != storage )
storage.Write( value );
}
// Write a long to storage
public void Write( long value )
throws StorageException
{
if ( null != storage )
storage.Write( value );
}
// Write a float to storage
public void Write( float value )
throws StorageException
{
if ( null != storage )
storage.Write( value );
}
// Write a double to storage
public void Write( double value )
throws StorageException
{
if ( null != storage )
storage.Write( value );
}
// Write a boolean to storage
public void Write( boolean value )
throws StorageException
{
if ( null != storage )
storage.Write( value );
}
// Read string from storage
public String Read( int length )
throws StorageException
{
if ( null != storage )
return storage.Read( length );
return null;
}
// Read byte from storage
public byte ReadByte()
throws StorageException
{
if ( null != storage )
return storage.ReadByte();
return -1;
}
// Read short from storage
public Short ReadShort()
throws StorageException
{
if ( null != storage )
return storage.ReadShort();
return -1;
}
// Read integer from storage
public Integer ReadInt()
throws StorageException
{
if ( null != storage )
return storage.ReadInt();
return -1;
}
// Read long from storage
public Long ReadLong()
throws StorageException
{
if ( null != storage )
return storage.ReadLong();
return -1L;
}
// Read float from storage
public float ReadFloat()
throws StorageException
{
if ( null != storage )
return storage.ReadFloat();
return -1;
}
// Read double from storage
public double ReadDouble()
throws StorageException
{
if ( null != storage )
return storage.ReadDouble();
return -1;
}
// Read boolean from storage
public boolean ReadBoolean()
throws StorageException
{
if ( null != storage )
return storage.ReadBoolean();
return false;
}
// Read a line from storage
public String ReadLine()
throws StorageException
{
if ( null != storage )
return storage.ReadLine();
return null;
}
// Method for dynamically specifying the primary keys
public void Primary( String[] primary )
throws IllegalArgumentException
{
schema.checkKeyArgs( primary );
this.primary = primary;
// No primary key
if ( null == primary )
return;
}
// Accessor for primary keys
public String[] Primary() {
return primary;
}
// Set the dynamic schema definition
public void Schema( ArrayList<Pair<String,String>> keys )
{
schema.Schema( keys );
}
// Method to check that keyVal arguments are valid
public void checkKeyValArgs( ArrayList<Pair<String,String>> keyVals )
throws IllegalArgumentException
{
schema.checkKeyValArgs( keyVals );
}
// Method to check that key arguments are valid
public void checkKeyArgs( String[] myKeys )
throws IllegalArgumentException
{
schema.checkKeyArgs( myKeys );
}
// Accessor Method: get keys from the schema
public ArrayList<Pair<String,String>> GetKeys()
{
return schema.GetKeys();
}
// Accessor Method: get type from the schema
public String GetType( String key )
{
return schema.GetType( key );
}
// Set Index Type
public void Index ( String type )
throws StorageException
{
switch ( type.toLowerCase() ) {
case "linked": index = new LinkedIndex( collectionName, primary );
break;
case "binary": index = new BinaryTreeIndex( collectionName, primary );
break;
default : throw new StorageException( "Invalid argument for index type (-I): " + type );
}
}
// Add entry to index
// Return
// -1 : new entry (not found)
// not -1 : position of found entry
public long Index( ArrayList<Pair<String,String>> keyVals )
throws StorageException
{
// no primary key
if ( null == primary )
return -1;
// Look for entries that are part of the primary key combination
String value = ""; // value accumulator
for ( String index : primary ) {
for ( Pair<String,String> keyVal : keyVals ) {
if ( index.equals( keyVal.getKey() ) ) {
// Hash the value for primary key field
value = value.concat( keyVal.getValue() );
break;
}
}
}
// Create hash code for entry to add to index
long hash = value.hashCode();
// Get position in storage for this entry
long pos = storage.Pos();
// Add entry to Index
return index.Add( hash, pos );
}
// Method for inserting into datastore
// keyvals:
// L = Name of Key that matches schema
// R = Value in String Representation
public abstract void Insert( ArrayList<Pair<String,String>> keyVals ) throws StorageException;
// Method for updating the datastore
// keyvals:
// L = Name of Key that matches schema
// R = Value in String Representation
// where: where clause for matching records
public abstract void Update( ArrayList<Pair<String,String>> keyVals, Where where );
// Method for deleting from datastore
// where: where clause for matching records
public abstract void Delete( Where where );
// Method for selecting rows from datastore
// keys: keys to selecting
// where: where clause for matching records
public abstract ArrayList<Data[]> Select( String[] keys, ArrayList<Where> where ) throws IllegalArgumentException, StorageException;
// Method for vacuuming a collection
public abstract void Vacuum();
}