Statistics
| Revision:

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

History | View | Annotate | Download (7.94 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.FileInputStream;
6
import java.io.IOException;
7
import java.io.RandomAccessFile;
8
import java.nio.channels.FileChannel;
9
import java.nio.channels.WritableByteChannel;
10
import java.sql.Types;
11

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

    
33
public class ShpWriter extends AbstractWriter implements ISpatialWriter {
34
        private String shpPath;
35
        private String shxPath;
36
        private String dbfPath;
37
        
38
        private File shpFile;
39

    
40
        private SHPFileWrite shpWrite;
41
        private DbaseFileWriterNIO dbfWrite;
42

    
43
        private DbaseFileHeaderNIO myHeader;
44

    
45
        private int shapeType;
46
        private int numRows;
47
        private int fileSize;
48
        private Rectangle2D fullExtent;
49
        private Object[] record;
50

    
51
        // private FLyrVect lyrVect;
52
        private FBitSet selection = null;
53

    
54
        public void setFile(File f)
55
        {
56
                shpPath = f.getAbsolutePath();
57

    
58
                String strFichshx = f.getAbsolutePath().replaceAll("\\.shp", ".shx");
59
                shxPath = strFichshx.replaceAll("\\.SHP", ".SHX");
60

    
61
                String strFichDbf = f.getAbsolutePath().replaceAll("\\.shp", ".dbf");
62
                dbfPath = strFichDbf.replaceAll("\\.SHP", ".DBF");
63
                
64
                shpFile = f;
65
        }
66

    
67
        private WritableByteChannel getWriteChannel(String path)
68
                                throws IOException
69
        {
70
                WritableByteChannel channel;
71

    
72
                File f = new File(path);
73

    
74
                if (!f.exists()) {
75
                        System.out.println("Creando fichero " + f.getAbsolutePath());
76

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

    
84
                RandomAccessFile raf = new RandomAccessFile(f, "rw");
85
                channel = raf.getChannel();
86

    
87
                return channel;
88
        }
89

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

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

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

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

    
159

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

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

    
173
                        try {
174
                                shpWrite.writeHeaders(new Rectangle2D.Double(),
175
                                                shapeType, 0, 0);
176

    
177
                                myHeader.setNumRecords(0);
178
                                dbfWrite = new DbaseFileWriterNIO(myHeader,
179
                                                (FileChannel) getWriteChannel(dbfPath));
180
                                record = new Object[myHeader.getNumFields()];
181
                                numRows = 0;
182
                                fullExtent = null;
183

    
184
                        } catch (IOException e) {
185
                                e.printStackTrace();
186
                                throw new EditionException(e);
187
                        }
188
                }
189

    
190

    
191
        }
192

    
193
        public void process(IRowEdited row) throws EditionException {
194
                IFeature feat = (IFeature) row.getLinkedRow();
195

    
196
                try {
197
                        /* System.out.println("Intento escribir el registro " +
198
                                        numRows + " de la capa " + lyrVect.getName()); */
199
                        fileSize = shpWrite.writeIGeometry(feat.getGeometry());
200
                        Rectangle2D boundsShp = feat.getGeometry().getBounds2D();
201

    
202
                        if (fullExtent == null) {
203
                                fullExtent = boundsShp;
204
                        } else {
205
                                fullExtent.add(boundsShp);
206
                        }
207

    
208
                        for (int i=0; i < record.length; i++)
209
                                record[i] = feat.getAttribute(i);
210
                        dbfWrite.write(record);
211
                        numRows++;
212

    
213
                } catch (IOException e) {
214
                        e.printStackTrace();
215
                        throw new EditionException(e);
216
                } catch (ShapefileException e) {
217
                        e.printStackTrace();
218
                        throw new EditionException(e);
219
                }
220

    
221
        }
222

    
223
        public void postProcess() throws EditionException {
224
                try {
225
                        myHeader.setNumRecords(numRows);
226
                        if (fullExtent == null)
227
                                fullExtent = new Rectangle2D.Double();
228
                        shpWrite.writeHeaders(fullExtent,
229
                                        shapeType, numRows, fileSize);
230

    
231
                        dbfWrite = new DbaseFileWriterNIO(myHeader,
232
                                        (FileChannel) getWriteChannel(dbfPath));
233
                } catch (IOException e) {
234
                        e.printStackTrace();
235
                        throw new EditionException(e);
236
                }
237

    
238

    
239
        }
240
        /**
241
         * Devuelve el path del fichero Shp.
242
         *
243
         * @author azabala
244
         * @return shp path
245
         */
246
        public String getShpPath(){
247
                //Lo necesito para que el ShpSchemaManager sepa
248
                //como "construir" el esquema del fichero SHP/DBF
249
                //adem?s del ShpLayerDefinition
250
                //TODO hacer que ShpWriter implemente ISchemaManager
251
                return this.shpPath;
252
        }
253

    
254
        public String getName() {
255
                return "Shape Writer";
256
        }
257
        public boolean canWriteGeometry(int gvSIGgeometryType) {
258
                switch (gvSIGgeometryType)
259
                {
260
                case FShape.POINT:
261
                        return true;
262
                case FShape.LINE:
263
                        return true;
264
                case FShape.POLYGON:
265
                        return true;
266
                case FShape.ARC:
267
                        return false;
268
                case FShape.ELLIPSE:
269
                        return false;                        
270
                case FShape.MULTIPOINT:
271
                        return true;                        
272
                case FShape.TEXT:
273
                        return false;                                                
274
                }
275
                return false;
276
        }
277

    
278
        public boolean canWriteAttribute(int sqlType) {
279
                switch (sqlType)
280
                {
281
                case Types.DOUBLE:
282
                case Types.FLOAT: 
283
                case Types.INTEGER:
284
                case Types.BIGINT:
285
                        return true;
286
                case Types.DATE:
287
                        return true;
288
                case Types.BIT:
289
                case Types.BOOLEAN:
290
                        return true;                        
291
                case Types.VARCHAR:
292
                case Types.CHAR: 
293
                case Types.LONGVARCHAR:
294
                        return true; // TODO: Revisar esto, porque no creo que admita campos muy grandes
295

    
296
                }
297
                
298
                return false;
299
        }
300

    
301
}