Statistics
| Revision:

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

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

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

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