Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / edition / writers / shp / ShpWriter.java @ 4740

History | View | Annotate | Download (8.06 KB)

1
package com.iver.cit.gvsig.fmap.edition.writers.shp;
2

    
3
import java.awt.geom.Rectangle2D;
4
import java.io.File;
5
import java.io.IOException;
6
import java.io.RandomAccessFile;
7
import java.nio.channels.FileChannel;
8
import java.nio.channels.WritableByteChannel;
9
import java.sql.Types;
10

    
11
import com.iver.cit.gvsig.fmap.DriverException;
12
import com.iver.cit.gvsig.fmap.core.FShape;
13
import com.iver.cit.gvsig.fmap.core.IFeature;
14
import com.iver.cit.gvsig.fmap.core.IGeometry;
15
import com.iver.cit.gvsig.fmap.drivers.LayerDefinition;
16
import com.iver.cit.gvsig.fmap.drivers.shp.DbaseFileHeaderNIO;
17
import com.iver.cit.gvsig.fmap.drivers.shp.DbaseFileWriterNIO;
18
import com.iver.cit.gvsig.fmap.drivers.shp.write.SHPFileWrite;
19
import com.iver.cit.gvsig.fmap.drivers.shp.write.ShapefileException;
20
import com.iver.cit.gvsig.fmap.edition.EditionException;
21
import com.iver.cit.gvsig.fmap.edition.IRowEdited;
22
import com.iver.cit.gvsig.fmap.edition.ISpatialWriter;
23
import com.iver.cit.gvsig.fmap.edition.writers.AbstractWriter;
24
import com.iver.cit.gvsig.fmap.layers.FBitSet;
25
import com.iver.cit.gvsig.fmap.layers.FLayer;
26
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
27
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
28

    
29
public class ShpWriter extends AbstractWriter implements ISpatialWriter {
30
        private String shpPath;
31
        private String shxPath;
32
        private String dbfPath;
33
        
34
        private File shpFile;
35

    
36
        private SHPFileWrite shpWrite;
37
        private DbaseFileWriterNIO dbfWrite;
38

    
39
        private DbaseFileHeaderNIO myHeader;
40

    
41
        private int shapeType;
42
        private int numRows;
43
        private int fileSize;
44
        private Rectangle2D fullExtent;
45
        private Object[] record;
46

    
47
        // private FLyrVect lyrVect;
48
        private FBitSet selection = null;
49
        private boolean bWriteHeaders = true;
50

    
51
        public void setFile(File f)
52
        {
53
                shpPath = f.getAbsolutePath();
54

    
55
                String strFichshx = f.getAbsolutePath().replaceAll("\\.shp", ".shx");
56
                shxPath = strFichshx.replaceAll("\\.SHP", ".SHX");
57

    
58
                String strFichDbf = f.getAbsolutePath().replaceAll("\\.shp", ".dbf");
59
                dbfPath = strFichDbf.replaceAll("\\.SHP", ".DBF");
60
                
61
                shpFile = f;
62
        }
63

    
64
        private WritableByteChannel getWriteChannel(String path)
65
                                throws IOException
66
        {
67
                WritableByteChannel channel;
68

    
69
                File f = new File(path);
70

    
71
                if (!f.exists()) {
72
                        System.out.println("Creando fichero " + f.getAbsolutePath());
73

    
74
                        if (!f.createNewFile()) {
75
                                System.err.print("Error al crear el fichero " +
76
                                        f.getAbsolutePath());
77
                                throw new IOException("Cannot create file " + f);
78
                        }
79
                }
80

    
81
                RandomAccessFile raf = new RandomAccessFile(f, "rw");
82
                channel = raf.getChannel();
83

    
84
                return channel;
85
        }
86

    
87
        /**
88
         * Util para crear un fichero .shp desde cero.
89
         * @param lyrDef
90
         * @throws IOException
91
         * @throws DriverException
92
         */
93
        /*public ShpWriter(File shpFile, LayerDefinition lyrDef) throws IOException, DriverException
94
        {
95
                myHeader = DbaseFileHeaderNIO.createDbaseHeader(lyrDef.getFieldsDesc());
96
                initialize(shpFile, lyrDef.getShapeType());
97
        }
98

99
        public ShpWriter(File shpFile, FLyrVect lyrVect) throws IOException, DriverException
100
        {
101
                SelectableDataSource sds = lyrVect.getRecordset();
102
                myHeader = DbaseFileHeaderNIO.createDbaseHeader(sds);
103

104
                initialize(shpFile, lyrVect.getShapeType());
105
        }
106
        */
107
        /**
108
         * Use this function first of all, when you need to prepare a writer
109
         * having a FLayer as model.
110
         * IMPORTANT: Call setFile before calling this function.
111
         * @param lyrVect
112
         * @throws IOException
113
         * @throws DriverException
114
         */
115
        public void initialize(FLayer layer) throws EditionException{
116
                if (layer instanceof FLyrVect)
117
                {
118
                        FLyrVect lyrVect = (FLyrVect) layer;                        
119
                        try {
120
                                SelectableDataSource sds = lyrVect.getRecordset();
121
                                myHeader = DbaseFileHeaderNIO.createDbaseHeader(sds);
122
                                initialize(shpFile, lyrVect.getShapeType());
123
                        } catch (IOException e) {
124
                                e.printStackTrace();
125
                                throw new EditionException(e);
126
                        } catch (DriverException e) {
127
                                e.printStackTrace();
128
                                throw new EditionException(e);
129
                        }                
130
                }
131
                else
132
                {
133
                        throw new EditionException("No se puede usar una capa que no es vectorial como modelo para escribir un shp.");
134
                }
135
        }
136
        /**
137
         * Useful to create a layer from scratch
138
         * Call setFile before using this function
139
         * @param lyrDef
140
         * @throws EditionException
141
         */
142
        public void initialize(LayerDefinition lyrDef) throws EditionException
143
        {
144
                myHeader = DbaseFileHeaderNIO.createDbaseHeader(lyrDef.getFieldsDesc());
145
                try {
146
                        initialize(shpFile, lyrDef.getShapeType());
147
                } catch (IOException e) {
148
                        e.printStackTrace();
149
                        throw new EditionException(e);
150
                }
151
        }
152
        
153

    
154
        private void initialize(File shpFile, int typeFShape) throws IOException //, FLyrVect lyrVect, FBitSet selection) throws IOException, DriverException
155
        {
156
                // this.lyrVect = lyrVect;
157
                // this.selection = selection;
158
                setFile(shpFile);
159

    
160

    
161
                shpWrite = new SHPFileWrite((FileChannel) getWriteChannel(shpPath),
162
                                (FileChannel) getWriteChannel(shxPath));
163
                shapeType = shpWrite.getShapeType(typeFShape);
164
        }
165

    
166
        public void preProcess() throws EditionException {
167
                // Por ahora solo escribimos los primeros bytes
168
                // de las cabeceras. Luego en el postprocess los escribiremos
169
                // correctamente, con el fullExtent y el numero de
170
                // registros que tocan.
171
                if (selection == null)
172
                {
173

    
174
                        try {
175
                                if (bWriteHeaders)
176
                                {
177
                                        shpWrite.writeHeaders(new Rectangle2D.Double(),
178
                                                shapeType, 0, 0);
179

    
180
                                }
181
                                myHeader.setNumRecords(0);
182
                                dbfWrite = new DbaseFileWriterNIO(myHeader,
183
                                        (FileChannel) getWriteChannel(dbfPath));
184

    
185
                                record = new Object[myHeader.getNumFields()];
186
                                numRows = 0;
187
                                fullExtent = null;
188

    
189
                        } catch (IOException e) {
190
                                e.printStackTrace();
191
                                throw new EditionException(e);
192
                        }
193
                }
194

    
195

    
196
        }
197

    
198
        public void process(IRowEdited row) throws EditionException {
199
                IFeature feat = (IFeature) row.getLinkedRow();
200

    
201
                try {
202
                        /* System.out.println("Intento escribir el registro " +
203
                                        numRows + " de la capa " + lyrVect.getName()); */
204
                        IGeometry theGeom = feat.getGeometry();
205
                        for (int i=0; i < record.length; i++)
206
                                record[i] = feat.getAttribute(i);
207
                        
208
                        fileSize = shpWrite.writeIGeometry(theGeom);
209
                        Rectangle2D boundsShp = theGeom.getBounds2D();
210

    
211
                        if (fullExtent == null) {
212
                                fullExtent = boundsShp;
213
                        } else {
214
                                fullExtent.add(boundsShp);
215
                        }
216

    
217
                        dbfWrite.write(record);
218
                        numRows++;
219

    
220
                } catch (IOException e) {
221
                        e.printStackTrace();
222
                        throw new EditionException(e);
223
                } catch (ShapefileException e) {
224
                        e.printStackTrace();
225
                        throw new EditionException(e);
226
                }
227

    
228
        }
229

    
230
        public void postProcess() throws EditionException {
231
                try {
232
                        myHeader.setNumRecords(numRows);
233
                        if (fullExtent == null)
234
                                fullExtent = new Rectangle2D.Double();
235
                        shpWrite.writeHeaders(fullExtent,
236
                                        shapeType, numRows, fileSize);
237

    
238
                        dbfWrite = new DbaseFileWriterNIO(myHeader,
239
                                        (FileChannel) getWriteChannel(dbfPath));
240
                } catch (IOException e) {
241
                        e.printStackTrace();
242
                        throw new EditionException(e);
243
                }
244

    
245

    
246
        }
247
        /**
248
         * Devuelve el path del fichero Shp.
249
         *
250
         * @author azabala
251
         * @return shp path
252
         */
253
        public String getShpPath(){
254
                //Lo necesito para que el ShpSchemaManager sepa
255
                //como "construir" el esquema del fichero SHP/DBF
256
                //adem?s del ShpLayerDefinition
257
                //TODO hacer que ShpWriter implemente ISchemaManager
258
                return this.shpPath;
259
        }
260

    
261
        public String getName() {
262
                return "Shape Writer";
263
        }
264
        public boolean canWriteGeometry(int gvSIGgeometryType) {
265
                switch (gvSIGgeometryType)
266
                {
267
                case FShape.POINT:
268
                        return true;
269
                case FShape.LINE:
270
                        return true;
271
                case FShape.POLYGON:
272
                        return true;
273
                case FShape.ARC:
274
                        return false;
275
                case FShape.ELLIPSE:
276
                        return false;                        
277
                case FShape.MULTIPOINT:
278
                        return true;                        
279
                case FShape.TEXT:
280
                        return false;                                                
281
                }
282
                return false;
283
        }
284

    
285
        public boolean canWriteAttribute(int sqlType) {
286
                switch (sqlType)
287
                {
288
                case Types.DOUBLE:
289
                case Types.FLOAT: 
290
                case Types.INTEGER:
291
                case Types.BIGINT:
292
                        return true;
293
                case Types.DATE:
294
                        return true;
295
                case Types.BIT:
296
                case Types.BOOLEAN:
297
                        return true;                        
298
                case Types.VARCHAR:
299
                case Types.CHAR: 
300
                case Types.LONGVARCHAR:
301
                        return true; // TODO: Revisar esto, porque no creo que admita campos muy grandes
302

    
303
                }
304
                
305
                return false;
306
        }
307

    
308
        /**
309
         * @param dontWriteHeaders The bDontWriteHeaders to set.
310
         */
311
        public void setWriteHeaders(boolean bWriteHeaders) {
312
                this.bWriteHeaders = bWriteHeaders;
313
        }
314

    
315
}