Statistics
| Revision:

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

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

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

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