Statistics
| Revision:

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

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 10046 jmvivo
        public ShpWriter() {
64
                super();
65
                this.capabilities.setProperty("FieldNameMaxLength","10");
66
        }
67 4430 fjp
        public void setFile(File f)
68 3653 fjp
        {
69
                shpPath = f.getAbsolutePath();
70
71
                String strFichshx = f.getAbsolutePath().replaceAll("\\.shp", ".shx");
72
                shxPath = strFichshx.replaceAll("\\.SHP", ".SHX");
73 3963 caballero
74 3653 fjp
                String strFichDbf = f.getAbsolutePath().replaceAll("\\.shp", ".dbf");
75
                dbfPath = strFichDbf.replaceAll("\\.SHP", ".DBF");
76 5389 caballero
77 4430 fjp
                shpFile = f;
78 3653 fjp
        }
79 3963 caballero
80 3653 fjp
        private WritableByteChannel getWriteChannel(String path)
81
                                throws IOException
82
        {
83
                WritableByteChannel channel;
84 3963 caballero
85 3653 fjp
                File f = new File(path);
86 3963 caballero
87 3653 fjp
                if (!f.exists()) {
88
                        System.out.println("Creando fichero " + f.getAbsolutePath());
89 3963 caballero
90 3653 fjp
                        if (!f.createNewFile()) {
91
                                System.err.print("Error al crear el fichero " +
92
                                        f.getAbsolutePath());
93
                                throw new IOException("Cannot create file " + f);
94
                        }
95
                }
96 3963 caballero
97 3653 fjp
                RandomAccessFile raf = new RandomAccessFile(f, "rw");
98
                channel = raf.getChannel();
99 3963 caballero
100 3653 fjp
                return channel;
101
        }
102 3963 caballero
103 3977 fjp
        /**
104
         * Util para crear un fichero .shp desde cero.
105
         * @param lyrDef
106
         * @throws IOException
107
         * @throws DriverException
108
         */
109 4143 caballero
        /*public ShpWriter(File shpFile, LayerDefinition lyrDef) throws IOException, DriverException
110 3977 fjp
        {
111 4084 azabala
                myHeader = DbaseFileHeaderNIO.createDbaseHeader(lyrDef.getFieldsDesc());
112 4078 azabala
                initialize(shpFile, lyrDef.getShapeType());
113 3977 fjp
        }
114 3963 caballero

115 3686 fjp
        public ShpWriter(File shpFile, FLyrVect lyrVect) throws IOException, DriverException
116 3653 fjp
        {
117 3977 fjp
                SelectableDataSource sds = lyrVect.getRecordset();
118
                myHeader = DbaseFileHeaderNIO.createDbaseHeader(sds);
119

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