Statistics
| Revision:

root / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / drivers / dbf / DBFDriver.java @ 28792

History | View | Annotate | Download (14.8 KB)

1
package com.iver.cit.gvsig.fmap.drivers.dbf;
2

    
3
import java.io.File;
4
import java.io.FileInputStream;
5
import java.io.FileNotFoundException;
6
import java.io.FileOutputStream;
7
import java.io.IOException;
8
import java.io.RandomAccessFile;
9
import java.io.UnsupportedEncodingException;
10
import java.nio.channels.FileChannel;
11
import java.nio.channels.WritableByteChannel;
12
import java.nio.charset.Charset;
13
import java.sql.Types;
14
import java.text.DateFormat;
15
import java.text.ParseException;
16
import java.util.Date;
17
import java.util.Locale;
18
import java.util.Properties;
19

    
20
import com.hardcode.gdbms.driver.DriverUtilities;
21
import com.hardcode.gdbms.driver.exceptions.BadFieldDriverException;
22
import com.hardcode.gdbms.driver.exceptions.CloseDriverException;
23
import com.hardcode.gdbms.driver.exceptions.InitializeWriterException;
24
import com.hardcode.gdbms.driver.exceptions.OpenDriverException;
25
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
26
import com.hardcode.gdbms.driver.exceptions.WriteDriverException;
27
import com.hardcode.gdbms.engine.data.DataSourceFactory;
28
import com.hardcode.gdbms.engine.data.driver.FileDriver;
29
import com.hardcode.gdbms.engine.data.edition.DataWare;
30
import com.hardcode.gdbms.engine.data.file.FileDataWare;
31
import com.hardcode.gdbms.engine.values.Value;
32
import com.hardcode.gdbms.engine.values.ValueFactory;
33
import com.iver.cit.gvsig.exceptions.visitors.ProcessWriterVisitorException;
34
import com.iver.cit.gvsig.exceptions.visitors.StartWriterVisitorException;
35
import com.iver.cit.gvsig.exceptions.visitors.StopWriterVisitorException;
36
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
37
import com.iver.cit.gvsig.fmap.drivers.ITableDefinition;
38
import com.iver.cit.gvsig.fmap.drivers.TableDefinition;
39
import com.iver.cit.gvsig.fmap.drivers.shp.DbaseFileHeaderNIO;
40
import com.iver.cit.gvsig.fmap.drivers.shp.DbaseFileWriterNIO;
41
import com.iver.cit.gvsig.fmap.edition.IRowEdited;
42
import com.iver.cit.gvsig.fmap.edition.IWriteable;
43
import com.iver.cit.gvsig.fmap.edition.IWriter;
44
import com.iver.cit.gvsig.fmap.edition.fieldmanagers.AbstractFieldManager;
45
import com.iver.cit.gvsig.fmap.edition.writers.dbf.DbfWriter;
46
import com.iver.utiles.NumberUtilities;
47

    
48

    
49
/**
50
 * DOCUMENT ME!
51
 *
52
 * @author Fernando Gonz?lez Cort?s
53
 */
54
public class DBFDriver extends AbstractFieldManager implements FileDriver, IWriteable, IWriter {
55
    //private File file;
56
    private static Locale ukLocale = new Locale("en", "UK"); // English, UK version
57
    private DbaseFile dbf = new DbaseFile();
58
    private char[] fieldTypes;
59
    private DataSourceFactory dsf;
60
    private DbfWriter dbfWriter = new DbfWriter();
61
        private File file = null;
62
        private static String tempDirectoryPath = System.getProperty("java.io.tmpdir");
63
        private File fTemp;
64
    private ITableDefinition tableDef;
65
        private Charset charSet = null;
66

    
67
    public Charset getCharSet() {
68
                return charSet;
69
        }
70

    
71
        public void setCharSet(Charset charSet) {
72
                this.charSet = charSet;
73
        }
74
    /**
75
     * @see com.hardcode.driverManager.Driver#getName()
76
     */
77
    public String getName() {
78
        return "gdbms dbf driver";
79
    }
80

    
81
    /**
82
     * @see com.hardcode.gdbms.engine.data.GDBMSDriver#open(java.io.File)
83
     */
84
    public void open(File file) throws OpenDriverException {
85
            this.file  = file;
86
        try {
87
        if (charSet != null)
88
                    dbf.setCharSet(charSet);
89
                        dbf.open(file);
90
                        // Despu?s de abrir el fichero sabemos cual es su charset
91
                setCharSet(dbf.getCharSet());
92
                    fieldTypes = new char[getFieldCount()];
93
            for (int i = 0; i < fieldTypes.length; i++) {
94
                fieldTypes[i] = dbf.getFieldType(i);
95
            }
96
                    int aux = (int)(Math.random() * 1000);
97
                    fTemp = new File(tempDirectoryPath + "/tmpDbf" + aux + ".dbf");
98
                    dbfWriter.setFile(fTemp);
99
                    if (charSet != null)
100
                            dbfWriter.setCharset(charSet);
101
        } catch (ReadDriverException e) {
102
                        throw new OpenDriverException(getName(),e);
103
                }
104

    
105
    }
106

    
107
    /**
108
     * @see com.hardcode.gdbms.engine.data.GDBMSDriver#close()
109
     */
110
    public void close() throws CloseDriverException {
111
        try {
112
                        dbf.close();
113
                } catch (IOException e) {
114
                        throw new CloseDriverException(getName(),e);
115
                }
116
    }
117

    
118
    /**
119
     * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldValue(long,
120
     *      int)
121
     */
122
    public Value getFieldValue(long rowIndex, int fieldId)
123
        throws ReadDriverException {
124
        // Field Type (C  or M)
125
        char cfieldType = fieldTypes[fieldId];
126
        int fieldType = getFieldType(fieldId);
127

    
128
            String strValue;
129

    
130

    
131
            if (cfieldType == 'D') {
132
            String date;
133
                        try {
134
                                date = dbf.getStringFieldValue((int) rowIndex, fieldId).trim();
135
                        } catch (UnsupportedEncodingException e1) {
136
                                throw new ReadDriverException(getName(),e1);
137
                        }
138
            // System.out.println(rowIndex + " data=" + date);
139
            if (date.length() == 0) {
140
                return null;
141
            }
142

    
143
            String year = date.substring(0, 4);
144
            String month = date.substring(4, 6);
145
            String day = date.substring(6, 8);
146
            DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, ukLocale);
147
            /* Calendar c = Calendar.getInstance();
148
            c.clear();
149
            c.set(Integer.parseInt(year), Integer.parseInt(month),
150
                Integer.parseInt(day));
151
            c.set(Calendar.MILLISECOND, 0); */
152
            String strAux = month + "/" + day + "/" + year;
153
            Date dat;
154
            try {
155
                dat = df.parse(strAux);
156
            } catch (ParseException e) {
157
                throw new ReadDriverException(getName(),e);
158
            }
159

    
160
            // System.out.println("numReg = " + rowIndex + " date:" + dat.getTime());
161

    
162
            return ValueFactory.createValue(dat);
163
        } else {
164

    
165
                try {
166
                        strValue = dbf.getStringFieldValue((int) rowIndex, fieldId);
167
                    } catch (UnsupportedEncodingException e1) {
168
                            throw new BadFieldDriverException(getName(),e1);
169
                    }
170
                           strValue = strValue.trim();
171
                           if (fieldType == Types.BOOLEAN){
172
                                   strValue = strValue.toLowerCase();
173
                                 strValue = Boolean.toString(strValue.equals("t") || strValue.equals("y"));
174
                           }
175

    
176
                    try {
177
                                return ValueFactory.createValueByType(strValue, fieldType);
178
                        } catch (Exception e) {
179
                                if (fieldType == Types.INTEGER ||
180
                                                fieldType == Types.BIGINT ||
181
                                                fieldType == Types.FLOAT ||
182
                                                fieldType == Types.DECIMAL ||
183
                                                fieldType == Types.DOUBLE){
184
                                        //Habria que quejarse???
185
                                        try {
186
                                                return ValueFactory.createValueByType("0", fieldType);
187
                                        } catch (ParseException e1) {
188
                                                throw new BadFieldDriverException(getName(),null,String.valueOf(fieldType));
189
                                        }
190
                                }else{
191
                                        // OJO: Habria que revisar el resto de tipos
192
                                        // De momento lanzamos la excepcion
193
                                        throw new BadFieldDriverException(getName(),null,String.valueOf(fieldType));
194
                                }
195
                        }
196

    
197

    
198
        }
199
    }
200

    
201
    /**
202
     * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldCount()
203
     */
204
    public int getFieldCount() throws ReadDriverException {
205
        return dbf.getFieldCount();
206
    }
207

    
208
    /**
209
     * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldName(int)
210
     */
211
    public String getFieldName(int fieldId) throws ReadDriverException {
212
        return dbf.getFieldName(fieldId);
213
    }
214

    
215
    /**
216
     * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getRowCount()
217
     */
218
    public long getRowCount() throws ReadDriverException {
219
        return dbf.getRecordCount();
220
    }
221

    
222
    /**
223
     * @see com.hardcode.gdbms.engine.data.driver.FileDriver#fileAccepted(java.io.File)
224
     */
225
    public boolean fileAccepted(File f) {
226
        return f.getAbsolutePath().toUpperCase().endsWith("DBF");
227
    }
228

    
229
    /**
230
     * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#getFieldType(int)
231
     */
232
    public int getFieldType(int i) throws ReadDriverException {
233
        char fieldType = fieldTypes[i];
234

    
235
        if (fieldType == 'L') {
236
            return Types.BOOLEAN;
237
        } else if ((fieldType == 'F') || (fieldType == 'N')) {
238
                if (dbf.getFieldDecimalLength(i)>0)
239
                        return Types.DOUBLE;
240
                else
241
                        return Types.INTEGER;
242
        } else if (fieldType == 'C') {
243
            return Types.VARCHAR;
244
        } else if (fieldType == 'D') {
245
            return Types.DATE;
246
        } else {
247
            throw new BadFieldDriverException(getName(),null,String.valueOf(fieldType));
248
        }
249
    }
250

    
251
    /**
252
     * @see com.hardcode.gdbms.engine.data.driver.DriverCommons#setDataSourceFactory(com.hardcode.gdbms.engine.data.DataSourceFactory)
253
     */
254
    public void setDataSourceFactory(DataSourceFactory dsf) {
255
        this.dsf = dsf;
256
    }
257

    
258
    private void writeToTemp(DataWare dataWare, File file) throws WriteDriverException, ReadDriverException {
259
        DbaseFileWriterNIO dbfWrite = null;
260
        DbaseFileHeaderNIO myHeader;
261
        Value[] record;
262

    
263
        try {
264
            myHeader = DbaseFileHeaderNIO.createDbaseHeader(dataWare);
265

    
266
            myHeader.setNumRecords((int) dataWare.getRowCount());
267
            dbfWrite = new DbaseFileWriterNIO(myHeader,
268
                    (FileChannel) getWriteChannel(file.getPath()));
269
            record = new Value[dataWare.getFieldCount()];
270

    
271
            for (int j = 0; j < dataWare.getRowCount(); j++) {
272
                for (int r = 0; r < dataWare.getFieldCount(); r++) {
273
                    record[r] = dataWare.getFieldValue(j, r);
274
                }
275

    
276
                dbfWrite.write(record);
277
            }
278

    
279
            dbfWrite.close();
280
        } catch (IOException e) {
281
            throw new WriteDriverException(getName(),e);
282
        }
283

    
284
    }
285

    
286
    /**
287
     * @throws ReadDriverException
288
     * @see com.hardcode.gdbms.engine.data.driver.FileDriver#writeFile(com.hardcode.gdbms.engine.data.file.FileDataWare,
289
     *      java.io.File)
290
     */
291
    public void writeFile(FileDataWare dataWare)
292
        throws WriteDriverException, ReadDriverException {
293

    
294
        String temp = dsf.getTempFile();
295

    
296
        writeToTemp(dataWare, new File(temp));
297

    
298
        try {
299
            FileChannel fcout = dbf.getWriteChannel();
300
            FileChannel fcin = new FileInputStream(temp).getChannel();
301

    
302
            DriverUtilities.copy(fcin, fcout);
303
        } catch (IOException e) {
304
            throw new WriteDriverException(getName(),e);
305
        }
306
    }
307

    
308
    /**
309
     * DOCUMENT ME!
310
     *
311
     * @param path DOCUMENT ME!
312
     *
313
     * @return DOCUMENT ME!
314
     *
315
     * @throws IOException DOCUMENT ME!
316
     */
317
    private WritableByteChannel getWriteChannel(String path)
318
        throws IOException {
319
        WritableByteChannel channel;
320

    
321
        File f = new File(path);
322

    
323
        if (!f.exists()) {
324
            System.out.println("Creando fichero " + f.getAbsolutePath());
325

    
326
            if (!f.createNewFile()) {
327
                throw new IOException("Cannot create file " + f);
328
            }
329
        }
330

    
331
        RandomAccessFile raf = new RandomAccessFile(f, "rw");
332
        channel = raf.getChannel();
333

    
334
        return channel;
335
    }
336

    
337
    /* (non-Javadoc)
338
     * @see com.hardcode.gdbms.engine.data.driver.FileDriver#createSource(java.lang.String, java.lang.String[], int[])
339
     */
340
    public void createSource(String arg0, String[] arg1, int[] arg2) throws ReadDriverException {
341
        DbaseFileHeaderNIO myHeader;
342

    
343
        int[] lengths = new int[arg2.length];
344
        for (int i = 0; i < arg2.length; i++) {
345
            lengths[i] = 100;
346
        }
347
        try {
348
                        myHeader = DbaseFileHeaderNIO.createDbaseHeader(arg1, arg2, lengths);
349

    
350
        myHeader.setNumRecords(0);
351
        DbaseFileWriterNIO dbfWrite = new DbaseFileWriterNIO(myHeader,
352
                (FileChannel) getWriteChannel(arg0));
353
        dbfWrite = new DbaseFileWriterNIO(myHeader,
354
                (FileChannel) getWriteChannel(arg0));
355
        } catch (IOException e) {
356
                        throw new ReadDriverException(getName(),e);
357
                }
358
    }
359

    
360
        public int getFieldWidth(int i) throws ReadDriverException {
361
                return dbf.getFieldLength(i);
362
        }
363

    
364
        public IWriter getWriter() {
365
                return this;
366
        }
367

    
368
        public void preProcess() throws StartWriterVisitorException {
369
                dbfWriter.setCharset(getCharSet());
370
                dbfWriter.preProcess();
371

    
372
        }
373

    
374
        public void process(IRowEdited row) throws ProcessWriterVisitorException {
375
                dbfWriter.process(row);
376

    
377
        }
378

    
379
        public void postProcess() throws StopWriterVisitorException {
380
                dbfWriter.postProcess();
381
                try {
382

    
383
                        // original encoding
384
                        short originalEncoding = dbf.getDbaseHeader().getLanguageID();
385

    
386
                        // Dbf
387
                        File dbfFile = fTemp;
388
                        FileChannel fcinDbf = new FileInputStream(dbfFile).getChannel();
389
                        FileChannel fcoutDbf = new FileOutputStream(file).getChannel();
390
                        DriverUtilities.copy(fcinDbf, fcoutDbf);
391

    
392
                        // Borramos los temporales
393
                        fTemp.delete();
394

    
395
                        // Reload
396
                        close();
397

    
398
                        // Restauramos el byte de encoding
399
                        RandomAccessFile fo = new RandomAccessFile(file, "rw");
400
                        fo.seek(29);
401
                        fo.writeByte(originalEncoding);
402
                        fo.close();
403

    
404
                        open(file);
405

    
406

    
407

    
408
                } catch (FileNotFoundException e) {
409
                        throw new StopWriterVisitorException(getName(),e);
410
                } catch (IOException e) {
411
                        throw new StopWriterVisitorException(getName(),e);
412
                } catch (CloseDriverException e) {
413
                        throw new StopWriterVisitorException(getName(),e);
414
                } catch (OpenDriverException e) {
415
                        throw new StopWriterVisitorException(getName(),e);
416
                }
417

    
418

    
419
        }
420

    
421
        public String getCapability(String capability) {
422
                return dbfWriter.getCapability(capability);
423
        }
424

    
425
        public void setCapabilities(Properties capabilities) {
426
                dbfWriter.setCapabilities(capabilities);
427

    
428
        }
429

    
430
        public boolean canWriteAttribute(int sqlType) {
431
                return dbfWriter.canWriteAttribute(sqlType);
432
        }
433

    
434
        public void initialize(ITableDefinition tableDefinition) throws InitializeWriterException {
435
                dbfWriter.initialize(tableDefinition);
436

    
437
        }
438

    
439
        public ITableDefinition getTableDefinition() throws ReadDriverException {
440
                tableDef = new TableDefinition();
441
                int numFields;
442
                        numFields = getFieldCount();
443
                        FieldDescription[] fieldsDescrip = new FieldDescription[numFields];
444
                        for (int i = 0; i < numFields; i++) {
445
                                fieldsDescrip[i] = new FieldDescription();
446
                                int type = getFieldType(i);
447
                                fieldsDescrip[i].setFieldType(type);
448
                                fieldsDescrip[i].setFieldName(getFieldName(i));
449
                                fieldsDescrip[i].setFieldLength(getFieldWidth(i));
450
                                if (NumberUtilities.isNumeric(type))
451
                                {
452
                                        if (!NumberUtilities.isNumericInteger(type))
453
                                                // TODO: If there is a lost in precision, this should be changed.
454
                                                fieldsDescrip[i].setFieldDecimalCount(6);
455
                                }
456
                                else
457
                                        fieldsDescrip[i].setFieldDecimalCount(0);
458
                                // TODO: ?DEFAULTVALUE?
459
                                // fieldsDescrip[i].setDefaultValue(get)
460
                        }
461

    
462
                        tableDef.setFieldsDesc(fieldsDescrip);
463
                        return tableDef;
464
//                return dbfWriter.getTableDefinition();
465
        }
466

    
467
        public boolean canAlterTable() {
468
                return true;
469
        }
470

    
471
        public boolean alterTable() {
472
                return true;
473
        }
474

    
475
        public boolean canSaveEdits() {
476
                if (file.canWrite()) return true;
477
                return false;
478

    
479
        }
480
        public boolean isWriteAll() {
481
                // TODO: DEVOLVER FALSE SI NO HA HABIDO CAMBIOS EN LOS CAMPOS.
482
                return true;
483
        }
484
        public void setFieldValue(int rowIndex, int fieldId, Object obj)
485
        throws IOException {
486
                dbf.setFieldValue(rowIndex,fieldId,obj);
487
        }
488
}