Statistics
| Revision:

svn-gvsig-desktop / tags / v10_RC2c / libraries / libFMap / src / com / iver / cit / gvsig / fmap / edition / writers / shp / ShpWriter.java @ 8745

History | View | Annotate | Download (10.2 KB)

1 3653 fjp
package com.iver.cit.gvsig.fmap.edition.writers.shp;
2
3 3672 fjp
import java.awt.geom.Rectangle2D;
4 3653 fjp
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 4328 fjp
import java.sql.Types;
10 3653 fjp
11 3672 fjp
import com.iver.cit.gvsig.fmap.DriverException;
12 4328 fjp
import com.iver.cit.gvsig.fmap.core.FShape;
13 3672 fjp
import com.iver.cit.gvsig.fmap.core.IFeature;
14 4564 fjp
import com.iver.cit.gvsig.fmap.core.IGeometry;
15 4937 fjp
import com.iver.cit.gvsig.fmap.drivers.ILayerDefinition;
16 5558 fjp
import com.iver.cit.gvsig.fmap.drivers.ITableDefinition;
17 3672 fjp
import com.iver.cit.gvsig.fmap.drivers.shp.DbaseFileHeaderNIO;
18
import com.iver.cit.gvsig.fmap.drivers.shp.DbaseFileWriterNIO;
19 3653 fjp
import com.iver.cit.gvsig.fmap.drivers.shp.write.SHPFileWrite;
20 3686 fjp
import com.iver.cit.gvsig.fmap.drivers.shp.write.ShapefileException;
21 3672 fjp
import com.iver.cit.gvsig.fmap.edition.EditionException;
22 3653 fjp
import com.iver.cit.gvsig.fmap.edition.IRowEdited;
23 4380 fjp
import com.iver.cit.gvsig.fmap.edition.ISpatialWriter;
24 4328 fjp
import com.iver.cit.gvsig.fmap.edition.writers.AbstractWriter;
25 3653 fjp
import com.iver.cit.gvsig.fmap.layers.FBitSet;
26 4440 fjp
import com.iver.cit.gvsig.fmap.layers.FLayer;
27 3672 fjp
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
28
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
29 3653 fjp
30 4380 fjp
public class ShpWriter extends AbstractWriter implements ISpatialWriter {
31 3653 fjp
        private String shpPath;
32
        private String shxPath;
33
        private String dbfPath;
34 5389 caballero
35 4430 fjp
        private File shpFile;
36 3963 caballero
37 3672 fjp
        private SHPFileWrite shpWrite;
38
        private DbaseFileWriterNIO dbfWrite;
39 4143 caballero
40 3977 fjp
        private DbaseFileHeaderNIO myHeader;
41 3963 caballero
42 3672 fjp
        private int shapeType;
43
        private int numRows;
44 3686 fjp
        private int fileSize;
45 3672 fjp
        private Rectangle2D fullExtent;
46
        private Object[] record;
47 3963 caballero
48 3977 fjp
        // private FLyrVect lyrVect;
49 3672 fjp
        private FBitSet selection = null;
50 4535 fjp
        private boolean bWriteHeaders = true;
51 5268 fjp
        private int gvSIG_geometryType;
52
        private int[] supportedGeometryTypes = {FShape.POINT,
53
                                                                                        FShape.LINE,
54
                                                                                        FShape.MULTIPOINT,
55
                                                                                        FShape.ARC,
56
                                                                                        FShape.CIRCLE,
57
                                                                                        FShape.POLYGON,
58
                                                                                        FShape.TEXT
59 5389 caballero
                                                                                        };
60 3963 caballero
61 4430 fjp
        public void setFile(File f)
62 3653 fjp
        {
63
                shpPath = f.getAbsolutePath();
64
65
                String strFichshx = f.getAbsolutePath().replaceAll("\\.shp", ".shx");
66
                shxPath = strFichshx.replaceAll("\\.SHP", ".SHX");
67 3963 caballero
68 3653 fjp
                String strFichDbf = f.getAbsolutePath().replaceAll("\\.shp", ".dbf");
69
                dbfPath = strFichDbf.replaceAll("\\.SHP", ".DBF");
70 5389 caballero
71 4430 fjp
                shpFile = f;
72 3653 fjp
        }
73 3963 caballero
74 3653 fjp
        private WritableByteChannel getWriteChannel(String path)
75
                                throws IOException
76
        {
77
                WritableByteChannel channel;
78 3963 caballero
79 3653 fjp
                File f = new File(path);
80 3963 caballero
81 3653 fjp
                if (!f.exists()) {
82
                        System.out.println("Creando fichero " + f.getAbsolutePath());
83 3963 caballero
84 3653 fjp
                        if (!f.createNewFile()) {
85
                                System.err.print("Error al crear el fichero " +
86
                                        f.getAbsolutePath());
87
                                throw new IOException("Cannot create file " + f);
88
                        }
89
                }
90 3963 caballero
91 3653 fjp
                RandomAccessFile raf = new RandomAccessFile(f, "rw");
92
                channel = raf.getChannel();
93 3963 caballero
94 3653 fjp
                return channel;
95
        }
96 3963 caballero
97 3977 fjp
        /**
98
         * Util para crear un fichero .shp desde cero.
99
         * @param lyrDef
100
         * @throws IOException
101
         * @throws DriverException
102
         */
103 4143 caballero
        /*public ShpWriter(File shpFile, LayerDefinition lyrDef) throws IOException, DriverException
104 3977 fjp
        {
105 4084 azabala
                myHeader = DbaseFileHeaderNIO.createDbaseHeader(lyrDef.getFieldsDesc());
106 4078 azabala
                initialize(shpFile, lyrDef.getShapeType());
107 3977 fjp
        }
108 3963 caballero

109 3686 fjp
        public ShpWriter(File shpFile, FLyrVect lyrVect) throws IOException, DriverException
110 3653 fjp
        {
111 3977 fjp
                SelectableDataSource sds = lyrVect.getRecordset();
112
                myHeader = DbaseFileHeaderNIO.createDbaseHeader(sds);
113

114
                initialize(shpFile, lyrVect.getShapeType());
115 3653 fjp
        }
116 4143 caballero
        */
117 4440 fjp
        /**
118
         * Use this function first of all, when you need to prepare a writer
119
         * having a FLayer as model.
120
         * IMPORTANT: Call setFile before calling this function.
121
         * @param lyrVect
122
         * @throws IOException
123
         * @throws DriverException
124
         */
125
        public void initialize(FLayer layer) throws EditionException{
126
                if (layer instanceof FLyrVect)
127
                {
128 5389 caballero
                        FLyrVect lyrVect = (FLyrVect) layer;
129 4440 fjp
                        try {
130 4455 fjp
                                SelectableDataSource sds = lyrVect.getRecordset();
131 4440 fjp
                                myHeader = DbaseFileHeaderNIO.createDbaseHeader(sds);
132
                                initialize(shpFile, lyrVect.getShapeType());
133
                        } catch (IOException e) {
134
                                e.printStackTrace();
135
                                throw new EditionException(e);
136
                        } catch (DriverException e) {
137
                                e.printStackTrace();
138
                                throw new EditionException(e);
139 5389 caballero
                        }
140 4440 fjp
                }
141
                else
142
                {
143
                        throw new EditionException("No se puede usar una capa que no es vectorial como modelo para escribir un shp.");
144
                }
145 4143 caballero
        }
146 4430 fjp
        /**
147 4440 fjp
         * Useful to create a layer from scratch
148
         * Call setFile before using this function
149
         * @param lyrDef
150 4740 fjp
         * @throws EditionException
151 4430 fjp
         */
152 5558 fjp
        public void initialize(ITableDefinition lyrDef) throws EditionException
153 4430 fjp
        {
154 6259 fjp
                super.initialize(lyrDef);
155 4440 fjp
                myHeader = DbaseFileHeaderNIO.createDbaseHeader(lyrDef.getFieldsDesc());
156 4740 fjp
                try {
157 5558 fjp
                        initialize(shpFile, ((ILayerDefinition)lyrDef).getShapeType());
158 4740 fjp
                } catch (IOException e) {
159
                        e.printStackTrace();
160
                        throw new EditionException(e);
161
                }
162 4440 fjp
        }
163 3977 fjp
164 5389 caballero
165 3977 fjp
        private void initialize(File shpFile, int typeFShape) throws IOException //, FLyrVect lyrVect, FBitSet selection) throws IOException, DriverException
166 3686 fjp
        {
167 3977 fjp
                // this.lyrVect = lyrVect;
168
                // this.selection = selection;
169 3653 fjp
                setFile(shpFile);
170
171 3963 caballero
172 3686 fjp
                shpWrite = new SHPFileWrite((FileChannel) getWriteChannel(shpPath),
173
                                (FileChannel) getWriteChannel(shxPath));
174 3977 fjp
                shapeType = shpWrite.getShapeType(typeFShape);
175 5268 fjp
                gvSIG_geometryType = typeFShape;
176
                setSupportedGeometryTypes();
177 3653 fjp
        }
178 3963 caballero
179 5268 fjp
        /**
180 5389 caballero
         *
181 5268 fjp
         */
182
        private void setSupportedGeometryTypes() {
183
                switch (gvSIG_geometryType)
184
                {
185
                case FShape.POINT:
186
                        supportedGeometryTypes = new int[] {FShape.POINT};
187
                        break;
188 6026 caballero
                case FShape.MULTIPOINT:
189
                        supportedGeometryTypes = new int[] {FShape.MULTIPOINT};
190
                        break;
191 5268 fjp
                case FShape.LINE:
192
                        supportedGeometryTypes = new int[] {FShape.LINE, FShape.ELLIPSE,
193
                                                        FShape.ARC, FShape.CIRCLE, FShape.POLYGON};
194
                        break;
195
                case FShape.POLYGON:
196
                        supportedGeometryTypes = new int[] {FShape.ELLIPSE,
197
                                FShape.CIRCLE, FShape.POLYGON};
198
                        break;
199 5389 caballero
200 5268 fjp
                default:
201
                        supportedGeometryTypes = new int[] {};
202
                }
203
        }
204
205 3672 fjp
        public void preProcess() throws EditionException {
206
                // Por ahora solo escribimos los primeros bytes
207
                // de las cabeceras. Luego en el postprocess los escribiremos
208 3963 caballero
                // correctamente, con el fullExtent y el numero de
209 3672 fjp
                // registros que tocan.
210
                if (selection == null)
211
                {
212 3963 caballero
213 3672 fjp
                        try {
214 4535 fjp
                                if (bWriteHeaders)
215
                                {
216
                                        shpWrite.writeHeaders(new Rectangle2D.Double(),
217 3686 fjp
                                                shapeType, 0, 0);
218 3963 caballero
219 4535 fjp
                                }
220 3672 fjp
                                myHeader.setNumRecords(0);
221
                                dbfWrite = new DbaseFileWriterNIO(myHeader,
222 4535 fjp
                                        (FileChannel) getWriteChannel(dbfPath));
223
224 3977 fjp
                                record = new Object[myHeader.getNumFields()];
225 3672 fjp
                                numRows = 0;
226
                                fullExtent = null;
227 3963 caballero
228 3672 fjp
                        } catch (IOException e) {
229
                                e.printStackTrace();
230
                                throw new EditionException(e);
231
                        }
232
                }
233 3653 fjp
234 3963 caballero
235 3653 fjp
        }
236
237 3672 fjp
        public void process(IRowEdited row) throws EditionException {
238 5389 caballero
239 4937 fjp
                if (row.getStatus() == IRowEdited.STATUS_DELETED) return;
240 5389 caballero
241 3963 caballero
                IFeature feat = (IFeature) row.getLinkedRow();
242
243 3672 fjp
                try {
244 3977 fjp
                        /* System.out.println("Intento escribir el registro " +
245
                                        numRows + " de la capa " + lyrVect.getName()); */
246 4564 fjp
                        IGeometry theGeom = feat.getGeometry();
247 5268 fjp
                        // Revisamos que podemos escribir esa entidad
248
                        // En un shpFile, podemos meter pol?gonos, pero que sean como
249
                        // lineas. En cambio, en uno de puntos solo se pueden meter puntos
250
                        if (canWriteGeometry(theGeom.getGeometryType()))
251
                        {
252
                                for (int i=0; i < record.length; i++)
253
                                        record[i] = feat.getAttribute(i);
254 5389 caballero
255 5268 fjp
                                fileSize = shpWrite.writeIGeometry(theGeom);
256
                                Rectangle2D boundsShp = theGeom.getBounds2D();
257 5389 caballero
258 5268 fjp
                                if (fullExtent == null) {
259
                                        fullExtent = boundsShp;
260
                                } else {
261
                                        fullExtent.add(boundsShp);
262
                                }
263 5389 caballero
264 5268 fjp
                                dbfWrite.write(record);
265
                                numRows++;
266 3672 fjp
                        }
267 5268 fjp
                        else
268
                        {
269 5389 caballero
                                System.out.println("No se ha escrito la geometr?a "
270 5268 fjp
                                                + row.getIndex() + " geomType=" + theGeom.getGeometryType());
271
                        }
272 3963 caballero
273 3672 fjp
                } catch (IOException e) {
274
                        e.printStackTrace();
275
                        throw new EditionException(e);
276 3686 fjp
                } catch (ShapefileException e) {
277
                        e.printStackTrace();
278
                        throw new EditionException(e);
279 3672 fjp
                }
280
281 3653 fjp
        }
282
283 3672 fjp
        public void postProcess() throws EditionException {
284 4143 caballero
                try {
285 3672 fjp
                        myHeader.setNumRecords(numRows);
286 4416 fjp
                        if (fullExtent == null)
287
                                fullExtent = new Rectangle2D.Double();
288 3963 caballero
                        shpWrite.writeHeaders(fullExtent,
289 3686 fjp
                                        shapeType, numRows, fileSize);
290 3963 caballero
291 3672 fjp
                        dbfWrite = new DbaseFileWriterNIO(myHeader,
292
                                        (FileChannel) getWriteChannel(dbfPath));
293
                } catch (IOException e) {
294
                        e.printStackTrace();
295
                        throw new EditionException(e);
296
                }
297 3653 fjp
298 3672 fjp
299 3653 fjp
        }
300 3973 azabala
        /**
301
         * Devuelve el path del fichero Shp.
302 4143 caballero
         *
303 3973 azabala
         * @author azabala
304
         * @return shp path
305
         */
306
        public String getShpPath(){
307
                //Lo necesito para que el ShpSchemaManager sepa
308
                //como "construir" el esquema del fichero SHP/DBF
309
                //adem?s del ShpLayerDefinition
310
                //TODO hacer que ShpWriter implemente ISchemaManager
311
                return this.shpPath;
312
        }
313 3653 fjp
314 4143 caballero
        public String getName() {
315
                return "Shape Writer";
316
        }
317 4328 fjp
        public boolean canWriteGeometry(int gvSIGgeometryType) {
318 5268 fjp
                /* switch (gvSIGgeometryType)
319 4328 fjp
                {
320
                case FShape.POINT:
321
                        return true;
322
                case FShape.LINE:
323
                        return true;
324
                case FShape.POLYGON:
325
                        return true;
326
                case FShape.ARC:
327 5268 fjp
                        return true; // Pero convirtiendo a segmentos peque?os
328 4328 fjp
                case FShape.ELLIPSE:
329 5268 fjp
                        return true; // Pero convirtiendo a segmentos peque?os
330 4328 fjp
                case FShape.MULTIPOINT:
331 5389 caballero
                        return true;
332 4328 fjp
                case FShape.TEXT:
333 5389 caballero
                        return false;
334 5268 fjp
                } */
335
                for (int i=0; i < supportedGeometryTypes.length; i++)
336
                {
337 7247 jaume
                        if (gvSIGgeometryType == supportedGeometryTypes[i] ||
338
                                gvSIGgeometryType == (supportedGeometryTypes[i] | FShape.Z)) // Jaume: support for 3D geometries
339 5268 fjp
                                return true;
340 4328 fjp
                }
341
                return false;
342
        }
343 4143 caballero
344 4328 fjp
        public boolean canWriteAttribute(int sqlType) {
345
                switch (sqlType)
346
                {
347
                case Types.DOUBLE:
348 5389 caballero
                case Types.FLOAT:
349 4328 fjp
                case Types.INTEGER:
350
                case Types.BIGINT:
351
                        return true;
352
                case Types.DATE:
353
                        return true;
354
                case Types.BIT:
355
                case Types.BOOLEAN:
356 5389 caballero
                        return true;
357 4328 fjp
                case Types.VARCHAR:
358 5389 caballero
                case Types.CHAR:
359 4328 fjp
                case Types.LONGVARCHAR:
360
                        return true; // TODO: Revisar esto, porque no creo que admita campos muy grandes
361
362
                }
363 5389 caballero
364 4328 fjp
                return false;
365
        }
366
367 4535 fjp
        /**
368
         * @param dontWriteHeaders The bDontWriteHeaders to set.
369
         */
370
        public void setWriteHeaders(boolean bWriteHeaders) {
371
                this.bWriteHeaders = bWriteHeaders;
372
        }
373
374 6714 caballero
//        public void setFlatness(double flatness) {
375
//                shpWrite.setFlatness(flatness);
376
//
377
//        }
378 5389 caballero
379 6621 fjp
        public boolean canAlterTable() {
380
                return true;
381
        }
382
383 6856 fjp
        public boolean canSaveEdits() {
384
                if (shpFile.canWrite())
385
                {
386
                        File auxShx = new File(shxPath);
387
                        if (auxShx.canWrite())
388
                        {
389
                                File auxDbf = new File(dbfPath);
390
                                if (auxDbf.canWrite())
391
                                        return true;
392
                        }
393
                }
394
                return false;
395
        }
396
397 3653 fjp
}