Statistics
| Revision:

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

History | View | Annotate | Download (15.3 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
import java.util.prefs.Preferences;
20

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

    
49

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

    
69
    public Charset getCharSet() {
70
                return charSet;
71
        }
72

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

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

    
112
    }
113

    
114
    /**
115
     * @see com.hardcode.gdbms.engine.data.GDBMSDriver#close()
116
     */
117
    public void close() throws CloseDriverException {
118
        try {
119
                        dbf.close();
120
                } catch (IOException e) {
121
                        throw new CloseDriverException(getName(),e);
122
                }
123
    }
124

    
125
    /**
126
     * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldValue(long,
127
     *      int)
128
     */
129
    public Value getFieldValue(long rowIndex, int fieldId)
130
        throws ReadDriverException {
131
        // Field Type (C  or M)
132
        char cfieldType = fieldTypes[fieldId];
133
        int fieldType = getFieldType(fieldId);
134

    
135
            String strValue;
136

    
137

    
138
            if (cfieldType == 'D') {
139
            String date;
140
                        try {
141
                                date = dbf.getStringFieldValue((int) rowIndex, fieldId).trim();
142
                        } catch (UnsupportedEncodingException e1) {
143
                                throw new ReadDriverException(getName(),e1);
144
                        }
145
            // System.out.println(rowIndex + " data=" + date);
146
            if (date.length()<8) {
147
                return null;
148
            }
149
            String year = date.substring(0, 4);
150
            String month = date.substring(4, 6);
151
            String day = date.substring(6, 8);
152
            DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, ukLocale);
153
            /* Calendar c = Calendar.getInstance();
154
            c.clear();
155
            c.set(Integer.parseInt(year), Integer.parseInt(month),
156
                Integer.parseInt(day));
157
            c.set(Calendar.MILLISECOND, 0); */
158
            String strAux = month + "/" + day + "/" + year;
159
            Date dat;
160
            try {
161
                dat = df.parse(strAux);
162
            } catch (ParseException e) {
163
                throw new ReadDriverException(getName(),e);
164
            }
165

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

    
168
            return ValueFactory.createValue(dat);
169
        } else {
170

    
171
                try {
172
                        strValue = dbf.getStringFieldValue((int) rowIndex, fieldId);
173
//                        System.out.println(strValue);
174
                    } catch (UnsupportedEncodingException e1) {
175
                            throw new BadFieldDriverException(getName(),e1);
176
                    }
177
                           strValue = strValue.trim();
178
                           if (fieldType == Types.BOOLEAN){
179
                                   strValue = strValue.toLowerCase();
180
                                 strValue = Boolean.toString(strValue.equals("t") || strValue.equals("y"));
181
                           }
182

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

    
204

    
205
        }
206
    }
207

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

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

    
222
    /**
223
     * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getRowCount()
224
     */
225
    public long getRowCount() throws ReadDriverException {
226
        return dbf.getRecordCount();
227
    }
228

    
229
    /**
230
     * @see com.hardcode.gdbms.engine.data.driver.FileDriver#fileAccepted(java.io.File)
231
     */
232
    public boolean fileAccepted(File f) {
233
        return f.getAbsolutePath().toUpperCase().endsWith("DBF");
234
    }
235

    
236
    /**
237
     * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#getFieldType(int)
238
     */
239
    public int getFieldType(int i) throws ReadDriverException {
240
        char fieldType = fieldTypes[i];
241

    
242
        if (fieldType == 'L') {
243
            return Types.BOOLEAN;
244
        } else if ((fieldType == 'F') || (fieldType == 'N')) {
245
                if (dbf.getFieldDecimalLength(i)>0 || dbf.getFieldLength(i)>9)
246
                        return Types.DOUBLE;
247
                else
248
                        return Types.INTEGER;
249
        } else if (fieldType == 'C') {
250
            return Types.VARCHAR;
251
        } else if (fieldType == 'D') {
252
            return Types.DATE;
253
        } else {
254
            throw new BadFieldDriverException(getName(),null,String.valueOf(fieldType));
255
        }
256
    }
257

    
258
    /**
259
     * @see com.hardcode.gdbms.engine.data.driver.DriverCommons#setDataSourceFactory(com.hardcode.gdbms.engine.data.DataSourceFactory)
260
     */
261
    public void setDataSourceFactory(DataSourceFactory dsf) {
262
        this.dsf = dsf;
263
    }
264

    
265
    private void writeToTemp(DataWare dataWare, File file) throws WriteDriverException, ReadDriverException {
266
        DbaseFileWriterNIO dbfWrite = null;
267
        DbaseFileHeaderNIO myHeader;
268
        Value[] record;
269

    
270
        try {
271
            myHeader = DbaseFileHeaderNIO.createDbaseHeader(dataWare);
272

    
273
            myHeader.setNumRecords((int) dataWare.getRowCount());
274
            dbfWrite = new DbaseFileWriterNIO(myHeader,
275
                    (FileChannel) getWriteChannel(file.getPath()));
276
            record = new Value[dataWare.getFieldCount()];
277

    
278
            for (int j = 0; j < dataWare.getRowCount(); j++) {
279
                for (int r = 0; r < dataWare.getFieldCount(); r++) {
280
                    record[r] = dataWare.getFieldValue(j, r);
281
                }
282

    
283
                dbfWrite.write(record);
284
            }
285

    
286
            dbfWrite.close();
287
        } catch (IOException e) {
288
            throw new WriteDriverException(getName(),e);
289
        }
290

    
291
    }
292

    
293
    /**
294
     * @throws ReadDriverException
295
     * @see com.hardcode.gdbms.engine.data.driver.FileDriver#writeFile(com.hardcode.gdbms.engine.data.file.FileDataWare,
296
     *      java.io.File)
297
     */
298
    public void writeFile(FileDataWare dataWare)
299
        throws WriteDriverException, ReadDriverException {
300

    
301
        String temp = dsf.getTempFile();
302

    
303
        writeToTemp(dataWare, new File(temp));
304

    
305
        try {
306
            FileChannel fcout = dbf.getWriteChannel();
307
            FileChannel fcin = new FileInputStream(temp).getChannel();
308

    
309
            DriverUtilities.copy(fcin, fcout);
310
        } catch (IOException e) {
311
            throw new WriteDriverException(getName(),e);
312
        }
313
    }
314

    
315
    /**
316
     * DOCUMENT ME!
317
     *
318
     * @param path DOCUMENT ME!
319
     *
320
     * @return DOCUMENT ME!
321
     *
322
     * @throws IOException DOCUMENT ME!
323
     */
324
    private WritableByteChannel getWriteChannel(String path)
325
        throws IOException {
326
        WritableByteChannel channel;
327

    
328
        File f = new File(path);
329

    
330
        if (!f.exists()) {
331
            System.out.println("Creando fichero " + f.getAbsolutePath());
332

    
333
            if (!f.createNewFile()) {
334
                throw new IOException("Cannot create file " + f);
335
            }
336
        }
337

    
338
        RandomAccessFile raf = new RandomAccessFile(f, "rw");
339
        channel = raf.getChannel();
340

    
341
        return channel;
342
    }
343

    
344
    /* (non-Javadoc)
345
     * @see com.hardcode.gdbms.engine.data.driver.FileDriver#createSource(java.lang.String, java.lang.String[], int[])
346
     */
347
    public void createSource(String arg0, String[] arg1, int[] arg2) throws ReadDriverException {
348
        DbaseFileHeaderNIO myHeader;
349

    
350
        int[] lengths = new int[arg2.length];
351
        for (int i = 0; i < arg2.length; i++) {
352
            lengths[i] = 100;
353
        }
354
        try {
355
                        myHeader = DbaseFileHeaderNIO.createDbaseHeader(arg1, arg2, lengths);
356

    
357
        myHeader.setNumRecords(0);
358
        DbaseFileWriterNIO dbfWrite = new DbaseFileWriterNIO(myHeader,
359
                (FileChannel) getWriteChannel(arg0));
360
        dbfWrite = new DbaseFileWriterNIO(myHeader,
361
                (FileChannel) getWriteChannel(arg0));
362
        } catch (IOException e) {
363
                        throw new ReadDriverException(getName(),e);
364
                }
365
    }
366

    
367
        public int getFieldWidth(int i) throws ReadDriverException {
368
                return dbf.getFieldLength(i);
369
        }
370

    
371
        public IWriter getWriter() {
372
                return this;
373
        }
374

    
375
        public void preProcess() throws StartWriterVisitorException {
376
                dbfWriter.setCharset(getCharSet());
377
                dbfWriter.preProcess();
378

    
379
        }
380

    
381
        public void process(IRowEdited row) throws ProcessWriterVisitorException {
382
                dbfWriter.process(row);
383

    
384
        }
385

    
386
        public void postProcess() throws StopWriterVisitorException {
387
                dbfWriter.postProcess();
388
                try {
389

    
390
                        // original encoding
391
                        short originalEncoding = dbf.getDbaseHeader().getLanguageID();
392

    
393
                        // Dbf
394
                        File dbfFile = fTemp;
395
                        FileChannel fcinDbf = new FileInputStream(dbfFile).getChannel();
396
                        FileChannel fcoutDbf = new FileOutputStream(file).getChannel();
397
                        DriverUtilities.copy(fcinDbf, fcoutDbf);
398

    
399
                        // Borramos los temporales
400
                        fTemp.delete();
401

    
402
                        // Reload
403
                        close();
404

    
405
                        // Restauramos el byte de encoding
406
                        RandomAccessFile fo = new RandomAccessFile(file, "rw");
407
                        fo.seek(29);
408
                        fo.writeByte(originalEncoding);
409
                        fo.close();
410

    
411
                        open(file);
412

    
413

    
414

    
415
                } catch (FileNotFoundException e) {
416
                        throw new StopWriterVisitorException(getName(),e);
417
                } catch (IOException e) {
418
                        throw new StopWriterVisitorException(getName(),e);
419
                } catch (CloseDriverException e) {
420
                        throw new StopWriterVisitorException(getName(),e);
421
                } catch (OpenDriverException e) {
422
                        throw new StopWriterVisitorException(getName(),e);
423
                }
424

    
425

    
426
        }
427

    
428
        public String getCapability(String capability) {
429
                return dbfWriter.getCapability(capability);
430
        }
431

    
432
        public void setCapabilities(Properties capabilities) {
433
                dbfWriter.setCapabilities(capabilities);
434

    
435
        }
436

    
437
        public boolean canWriteAttribute(int sqlType) {
438
                return dbfWriter.canWriteAttribute(sqlType);
439
        }
440

    
441
        public void initialize(ITableDefinition tableDefinition) throws InitializeWriterException {
442
                dbfWriter.initialize(tableDefinition);
443

    
444
        }
445

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

    
469
                        tableDef.setFieldsDesc(fieldsDescrip);
470
                        return tableDef;
471
//                return dbfWriter.getTableDefinition();
472
        }
473

    
474
        public boolean canAlterTable() {
475
                return true;
476
        }
477

    
478
        public boolean alterTable() {
479
                return true;
480
        }
481

    
482
        public boolean canSaveEdits() {
483
                if (file.canWrite()) return true;
484
                return false;
485

    
486
        }
487
        public boolean isWriteAll() {
488
                // TODO: DEVOLVER FALSE SI NO HA HABIDO CAMBIOS EN LOS CAMPOS.
489
                return true;
490
        }
491
        public void setFieldValue(int rowIndex, int fieldId, Object obj)
492
        throws IOException {
493
                dbf.setFieldValue(rowIndex,fieldId,obj);
494
        }
495
}