Statistics
| Revision:

root / branches / v10 / libraries / libFMap / src / com / iver / cit / gvsig / fmap / drivers / dbf / DBFDriver.java @ 12534

History | View | Annotate | Download (12.6 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.sql.Types;
13
import java.text.DateFormat;
14
import java.text.ParseException;
15
import java.util.Date;
16
import java.util.Locale;
17
import java.util.Properties;
18

    
19
import com.hardcode.gdbms.driver.DriverUtilities;
20
import com.hardcode.gdbms.engine.data.DataSourceFactory;
21
import com.hardcode.gdbms.engine.data.driver.DriverException;
22
import com.hardcode.gdbms.engine.data.driver.FileDriver;
23
import com.hardcode.gdbms.engine.data.edition.DataWare;
24
import com.hardcode.gdbms.engine.data.file.FileDataWare;
25
import com.hardcode.gdbms.engine.values.Value;
26
import com.hardcode.gdbms.engine.values.ValueFactory;
27
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
28
import com.iver.cit.gvsig.fmap.drivers.ITableDefinition;
29
import com.iver.cit.gvsig.fmap.drivers.TableDefinition;
30
import com.iver.cit.gvsig.fmap.drivers.shp.DbaseFileHeaderNIO;
31
import com.iver.cit.gvsig.fmap.drivers.shp.DbaseFileWriterNIO;
32
import com.iver.cit.gvsig.fmap.edition.EditionException;
33
import com.iver.cit.gvsig.fmap.edition.IRowEdited;
34
import com.iver.cit.gvsig.fmap.edition.IWriteable;
35
import com.iver.cit.gvsig.fmap.edition.IWriter;
36
import com.iver.cit.gvsig.fmap.edition.fieldmanagers.AbstractFieldManager;
37
import com.iver.cit.gvsig.fmap.edition.writers.dbf.DbfWriter;
38
import com.iver.utiles.NumberUtilities;
39

    
40

    
41
/**
42
 * DOCUMENT ME!
43
 *
44
 * @author Fernando Gonz?lez Cort?s
45
 */
46
public class DBFDriver extends AbstractFieldManager implements FileDriver, IWriteable, IWriter {
47
    //private File file;
48
    private static Locale ukLocale = new Locale("en", "UK"); // English, UK version
49
    private DbaseFile dbf = new DbaseFile();
50
    private char[] fieldTypes;
51
    private DataSourceFactory dsf;
52
    private DbfWriter dbfWriter = new DbfWriter();
53
        private File file = null;
54
        private static String tempDirectoryPath = System.getProperty("java.io.tmpdir");
55
        private File fTemp;
56
    private ITableDefinition tableDef;
57

    
58
    /**
59
     * @see com.hardcode.driverManager.Driver#getName()
60
     */
61
    public String getName() {
62
        return "gdbms dbf driver";
63
    }
64

    
65
    /**
66
     * @see com.hardcode.gdbms.engine.data.GDBMSDriver#open(java.io.File)
67
     */
68
    public void open(File file) throws IOException {
69
            this.file  = file;
70
        dbf.open(file);
71

    
72
        try {
73
            fieldTypes = new char[getFieldCount()];
74

    
75
            for (int i = 0; i < fieldTypes.length; i++) {
76
                fieldTypes[i] = dbf.getFieldType(i);
77
            }
78
                    int aux = (int)(Math.random() * 1000);
79
                    fTemp = new File(tempDirectoryPath + "/tmpDbf" + aux + ".dbf");
80
                    dbfWriter.setFile(fTemp);
81
        } catch (DriverException e) {
82
            throw new IOException(e.getMessage());
83
        }
84

    
85
    }
86

    
87
    /**
88
     * @see com.hardcode.gdbms.engine.data.GDBMSDriver#close()
89
     */
90
    public void close() throws IOException {
91
        dbf.close();
92
    }
93

    
94
    /**
95
     * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldValue(long,
96
     *      int)
97
     */
98
    public Value getFieldValue(long rowIndex, int fieldId)
99
        throws DriverException {
100
        // Field Type (C  or M)
101
        char cfieldType = fieldTypes[fieldId];
102
            int fieldType = getFieldType(fieldId);
103

    
104
            String strValue;
105

    
106
        if (cfieldType == 'D') {
107
            String date;
108
                        try {
109
                                date = dbf.getStringFieldValue((int) rowIndex, fieldId).trim();
110
                        } catch (UnsupportedEncodingException e1) {
111
                                throw new DriverException(e1);
112
                        }
113
            // System.out.println(rowIndex + " data=" + date);
114
            if (date.length() == 0) {
115
                return null;
116
            }
117

    
118
            String year = date.substring(0, 4);
119
            String month = date.substring(4, 6);
120
            String day = date.substring(6, 8);
121
            DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, ukLocale);
122
            /* Calendar c = Calendar.getInstance();
123
            c.clear();
124
            c.set(Integer.parseInt(year), Integer.parseInt(month),
125
                Integer.parseInt(day));
126
            c.set(Calendar.MILLISECOND, 0); */
127
            String strAux = month + "/" + day + "/" + year;
128
            Date dat;
129
            try {
130
                dat = df.parse(strAux);
131
            } catch (ParseException e) {
132
                throw new DriverException("Bad Date Format");
133
            }
134

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

    
137
            return ValueFactory.createValue(dat);
138
        } else {
139
                try {
140
                        strValue = dbf.getStringFieldValue((int) rowIndex, fieldId);
141
                    } catch (UnsupportedEncodingException e1) {
142
                            e1.printStackTrace();
143
                            throw new DriverException(e1);
144
                    }
145
                           strValue = strValue.trim();
146
                           if (fieldType == Types.BOOLEAN){
147
                                   strValue = strValue.toLowerCase();
148
                                 strValue = Boolean.toString(strValue.equals("t") || strValue.equals("y"));
149
                           }
150

    
151
                    try {
152
                                return ValueFactory.createValueByType(strValue, fieldType);
153
                        } catch (ParseException e) {
154
                                throw new DriverException("Bad Field Value: '" + strValue+"' (rowIndes: "+rowIndex + " fielId: "+ fieldId +" fieldType: " + fieldType+ " )");
155
                        }
156
        }
157
    }
158

    
159
    /**
160
     * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldCount()
161
     */
162
    public int getFieldCount() throws DriverException {
163
        return dbf.getFieldCount();
164
    }
165

    
166
    /**
167
     * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getFieldName(int)
168
     */
169
    public String getFieldName(int fieldId) throws DriverException {
170
        return dbf.getFieldName(fieldId);
171
    }
172

    
173
    /**
174
     * @see com.hardcode.gdbms.engine.data.driver.ReadAccess#getRowCount()
175
     */
176
    public long getRowCount() throws DriverException {
177
        return dbf.getRecordCount();
178
    }
179

    
180
    /**
181
     * @see com.hardcode.gdbms.engine.data.driver.FileDriver#fileAccepted(java.io.File)
182
     */
183
    public boolean fileAccepted(File f) {
184
        return f.getAbsolutePath().toUpperCase().endsWith("DBF");
185
    }
186

    
187
    /**
188
     * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#getFieldType(int)
189
     */
190
    public int getFieldType(int i) throws DriverException {
191
        char fieldType = fieldTypes[i];
192

    
193
        if (fieldType == 'L') {
194
            return Types.BOOLEAN;
195
        } else if ((fieldType == 'F') || (fieldType == 'N')) {
196
                if (dbf.getFieldDecimalLength(i)>0)
197
                        return Types.DOUBLE;
198
                else
199
                        return Types.INTEGER;
200
        } else if (fieldType == 'C') {
201
            return Types.VARCHAR;
202
        } else if (fieldType == 'D') {
203
            return Types.DATE;
204
        } else {
205
            throw new DriverException("Unknown field type");
206
        }
207
    }
208

    
209
    /**
210
     * @see com.hardcode.gdbms.engine.data.driver.DriverCommons#setDataSourceFactory(com.hardcode.gdbms.engine.data.DataSourceFactory)
211
     */
212
    public void setDataSourceFactory(DataSourceFactory dsf) {
213
        this.dsf = dsf;
214
    }
215

    
216
    private void writeToTemp(DataWare dataWare, File file) throws DriverException {
217
        DbaseFileWriterNIO dbfWrite = null;
218
        DbaseFileHeaderNIO myHeader;
219
        Value[] record;
220

    
221
        try {
222
            myHeader = DbaseFileHeaderNIO.createDbaseHeader(dataWare);
223

    
224
            myHeader.setNumRecords((int) dataWare.getRowCount());
225
            dbfWrite = new DbaseFileWriterNIO(myHeader,
226
                    (FileChannel) getWriteChannel(file.getPath()));
227
            record = new Value[dataWare.getFieldCount()];
228

    
229
            for (int j = 0; j < dataWare.getRowCount(); j++) {
230
                for (int r = 0; r < dataWare.getFieldCount(); r++) {
231
                    record[r] = dataWare.getFieldValue(j, r);
232
                }
233

    
234
                dbfWrite.write(record);
235
            }
236

    
237
            dbfWrite.close();
238
        } catch (IOException e) {
239
            throw new DriverException(e);
240
        }
241

    
242
    }
243

    
244
    /**
245
     * @see com.hardcode.gdbms.engine.data.driver.FileDriver#writeFile(com.hardcode.gdbms.engine.data.file.FileDataWare,
246
     *      java.io.File)
247
     */
248
    public void writeFile(FileDataWare dataWare)
249
        throws DriverException {
250

    
251
        String temp = dsf.getTempFile();
252

    
253
        writeToTemp(dataWare, new File(temp));
254

    
255
        try {
256
            FileChannel fcout = dbf.getWriteChannel();
257
            FileChannel fcin = new FileInputStream(temp).getChannel();
258

    
259
            DriverUtilities.copy(fcin, fcout);
260
        } catch (IOException e) {
261
            throw new DriverException(e);
262
        }
263
    }
264

    
265
    /**
266
     * DOCUMENT ME!
267
     *
268
     * @param path DOCUMENT ME!
269
     *
270
     * @return DOCUMENT ME!
271
     *
272
     * @throws IOException DOCUMENT ME!
273
     */
274
    private WritableByteChannel getWriteChannel(String path)
275
        throws IOException {
276
        WritableByteChannel channel;
277

    
278
        File f = new File(path);
279

    
280
        if (!f.exists()) {
281
            System.out.println("Creando fichero " + f.getAbsolutePath());
282

    
283
            if (!f.createNewFile()) {
284
                throw new IOException("Cannot create file " + f);
285
            }
286
        }
287

    
288
        RandomAccessFile raf = new RandomAccessFile(f, "rw");
289
        channel = raf.getChannel();
290

    
291
        return channel;
292
    }
293

    
294
    /* (non-Javadoc)
295
     * @see com.hardcode.gdbms.engine.data.driver.FileDriver#createSource(java.lang.String, java.lang.String[], int[])
296
     */
297
    public void createSource(String arg0, String[] arg1, int[] arg2) throws IOException {
298
        DbaseFileHeaderNIO myHeader;
299

    
300
        int[] lengths = new int[arg2.length];
301
        for (int i = 0; i < arg2.length; i++) {
302
            lengths[i] = 100;
303
        }
304
        myHeader = DbaseFileHeaderNIO.createDbaseHeader(arg1, arg2, lengths);
305
        myHeader.setNumRecords(0);
306
        DbaseFileWriterNIO dbfWrite = new DbaseFileWriterNIO(myHeader,
307
                (FileChannel) getWriteChannel(arg0));
308
        dbfWrite = new DbaseFileWriterNIO(myHeader,
309
                (FileChannel) getWriteChannel(arg0));
310
    }
311

    
312
        public int getFieldWidth(int i) throws DriverException {
313
                return dbf.getFieldLength(i);
314
        }
315

    
316
        public IWriter getWriter() {
317
                return this;
318
        }
319

    
320
        public void preProcess() throws EditionException {
321
                dbfWriter.preProcess();
322

    
323
        }
324

    
325
        public void process(IRowEdited row) throws EditionException {
326
                dbfWriter.process(row);
327

    
328
        }
329

    
330
        public void postProcess() throws EditionException {
331
                dbfWriter.postProcess();
332
                try {
333
                        // Dbf
334
                        File dbfFile = fTemp;
335
                        FileChannel fcinDbf = new FileInputStream(dbfFile).getChannel();
336
                        FileChannel fcoutDbf = new FileOutputStream(file).getChannel();
337
                        DriverUtilities.copy(fcinDbf, fcoutDbf);
338

    
339
                        // Borramos los temporales
340
                        fTemp.delete();
341

    
342
                        // Reload
343
                        close();
344
                        open(file);
345

    
346

    
347

    
348
                } catch (FileNotFoundException e) {
349
                        throw new EditionException(e);
350
                } catch (IOException e) {
351
                        throw new EditionException(e);
352
                }
353

    
354

    
355
        }
356

    
357
        public String getCapability(String capability) {
358
                return dbfWriter.getCapability(capability);
359
        }
360

    
361
        public void setCapabilities(Properties capabilities) {
362
                dbfWriter.setCapabilities(capabilities);
363

    
364
        }
365

    
366
        public boolean canWriteAttribute(int sqlType) {
367
                return dbfWriter.canWriteAttribute(sqlType);
368
        }
369

    
370
        public void initialize(ITableDefinition tableDefinition) throws EditionException {
371
                dbfWriter.initialize(tableDefinition);
372

    
373
        }
374

    
375
        public ITableDefinition getTableDefinition() {
376
                tableDef = new TableDefinition();
377
                int numFields;
378
                try {
379
                        numFields = getFieldCount();
380
                        FieldDescription[] fieldsDescrip = new FieldDescription[numFields];
381
                        for (int i = 0; i < numFields; i++) {
382
                                fieldsDescrip[i] = new FieldDescription();
383
                                int type = getFieldType(i);
384
                                fieldsDescrip[i].setFieldType(type);
385
                                fieldsDescrip[i].setFieldName(getFieldName(i));
386
                                fieldsDescrip[i].setFieldLength(getFieldWidth(i));
387
                                if (NumberUtilities.isNumeric(type))
388
                                {
389
                                        if (!NumberUtilities.isNumericInteger(type))
390
                                                // TODO: If there is a lost in precision, this should be changed.
391
                                                fieldsDescrip[i].setFieldDecimalCount(6);
392
                                }
393
                                else
394
                                        fieldsDescrip[i].setFieldDecimalCount(0);
395
                                // TODO: ?DEFAULTVALUE?
396
                                // fieldsDescrip[i].setDefaultValue(get)
397
                        }
398

    
399
                        tableDef.setFieldsDesc(fieldsDescrip);
400
                        return tableDef;
401
                } catch (DriverException e) {
402
                        // TODO Auto-generated catch block
403
                        e.printStackTrace();
404
                }
405
                return null;
406
//                return dbfWriter.getTableDefinition();
407
        }
408

    
409
        public boolean canAlterTable() {
410
                return true;
411
        }
412

    
413
        public boolean alterTable() throws EditionException {
414
                return true;
415
        }
416

    
417
        public boolean canSaveEdits() {
418
                if (file.canWrite()) return true;
419
                return false;
420

    
421
        }
422

    
423
        public boolean isWriteAll() {
424
                // TODO: DEVOLVER FALSE SI NO HA HABIDO CAMBIOS EN LOS CAMPOS.
425
                return true;
426
        }
427

    
428
}