Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_dalfile / src / org / gvsig / fmap / dal / store / dgn / DGNStoreProvider.java @ 32880

History | View | Annotate | Download (30.6 KB)

1
package org.gvsig.fmap.dal.store.dgn;
2

    
3
import java.awt.geom.AffineTransform;
4
import java.awt.geom.Arc2D;
5
import java.io.File;
6
import java.util.ArrayList;
7
import java.util.HashMap;
8
import java.util.Iterator;
9
import java.util.List;
10
import java.util.Map;
11

    
12
import org.cresques.cts.IProjection;
13
import org.gvsig.fmap.dal.DALLocator;
14
import org.gvsig.fmap.dal.DataManager;
15
import org.gvsig.fmap.dal.DataServerExplorer;
16
import org.gvsig.fmap.dal.DataStoreNotification;
17
import org.gvsig.fmap.dal.DataTypes;
18
import org.gvsig.fmap.dal.FileHelper;
19
import org.gvsig.fmap.dal.exception.DataException;
20
import org.gvsig.fmap.dal.exception.InitializeException;
21
import org.gvsig.fmap.dal.exception.OpenException;
22
import org.gvsig.fmap.dal.exception.ReadException;
23
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
24
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
25
import org.gvsig.fmap.dal.feature.EditableFeatureType;
26
import org.gvsig.fmap.dal.feature.FeatureStore;
27
import org.gvsig.fmap.dal.feature.FeatureType;
28
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
29
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
30
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices;
31
import org.gvsig.fmap.dal.feature.spi.memory.AbstractMemoryStoreProvider;
32
import org.gvsig.fmap.dal.resource.ResourceAction;
33
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
34
import org.gvsig.fmap.dal.resource.file.FileResource;
35
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
36
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
37
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorer;
38
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorerParameters;
39
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
40
import org.gvsig.fmap.dal.store.dgn.lib.DGNElemArc;
41
import org.gvsig.fmap.dal.store.dgn.lib.DGNElemComplexHeader;
42
import org.gvsig.fmap.dal.store.dgn.lib.DGNElemCore;
43
import org.gvsig.fmap.dal.store.dgn.lib.DGNElemMultiPoint;
44
import org.gvsig.fmap.dal.store.dgn.lib.DGNElemText;
45
import org.gvsig.fmap.dal.store.dgn.lib.DGNFileHeader;
46
import org.gvsig.fmap.dal.store.dgn.lib.DGNReader;
47
import org.gvsig.fmap.geom.Geometry;
48
import org.gvsig.fmap.geom.GeometryLocator;
49
import org.gvsig.fmap.geom.GeometryManager;
50
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
51
import org.gvsig.fmap.geom.Geometry.TYPES;
52
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
53
import org.gvsig.fmap.geom.exception.CreateGeometryException;
54
import org.gvsig.fmap.geom.primitive.Envelope;
55
import org.gvsig.fmap.geom.primitive.GeneralPathX;
56
import org.gvsig.fmap.geom.primitive.Point;
57
import org.gvsig.metadata.MetadataLocator;
58
import org.gvsig.metadata.MetadataManager;
59
import org.gvsig.metadata.exceptions.MetadataException;
60
import org.gvsig.tools.dynobject.DynStruct;
61
import org.gvsig.tools.dynobject.exception.DynMethodException;
62

    
63
public class DGNStoreProvider extends AbstractMemoryStoreProvider implements
64
                ResourceConsumer {
65
//        private static final Logger logger = LoggerFactory.getLogger(DGNStoreProvider.class);
66

    
67
        public static final String NAME = "DGN";
68
        public static final String DESCRIPTION = "DGN file";
69
        
70
        public static final String METADATA_DEFINITION_NAME = NAME;
71
        private static final String METADATA_DEFINITION_DESCRIPTION = "DGN File Store";
72

    
73
        private static final String NAME_FIELD_ID = "ID";
74
        private static final String NAME_FIELD_GEOMETRY = "Geometry";
75
        private static final String NAME_FIELD_ENTITY = "Entity";
76
        private static final String NAME_FIELD_LAYER = "Layer";
77
        public static final String NAME_FIELD_COLOR = "Color";
78
//        private static final String NAME_FIELD_ELEVATION = "Elevation";
79
//        private static final String NAME_FIELD_THICKNESS = "Thickness";
80
        public static final String NAME_FIELD_TEXT = "Text";
81
        public static final String NAME_FIELD_HEIGHTTEXT = "HeightText";
82
        public static final String NAME_FIELD_ROTATIONTEXT = "Rotation";
83

    
84

    
85
        private int ID_FIELD_ID = 0;
86
        private int ID_FIELD_ENTITY = 1;
87
        private int ID_FIELD_LAYER = 2;
88
        private int ID_FIELD_COLOR = 3;
89
//        private int ID_FIELD_ELEVATION = 4;
90
//        private int ID_FIELD_THICKNESS = 5;
91
        private int ID_FIELD_TEXT = 6;
92
        private int ID_FIELD_HEIGHTTEXT = 7;
93
        private int ID_FIELD_ROTATIONTEXT = 8;
94
//        private int ID_FIELD_GEOMETRY = 9;
95

    
96
        private IProjection projection;
97
        private ResourceProvider resource;
98
        private LegendBuilder legendBuilder;
99

    
100
        private long counterNewsOIDs = 0;
101
        protected GeometryManager geomManager = GeometryLocator.getGeometryManager();
102

    
103
        public DGNStoreProvider(DGNStoreParameters parameters,
104
                        DataStoreProviderServices storeServices) throws InitializeException {
105
                super(
106
                        parameters, 
107
                        storeServices, 
108
                        FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME)
109
                );
110

    
111
                counterNewsOIDs = 0;
112
                //                projection = CRSFactory.getCRS(getParameters().getSRSID());
113

    
114
                File file = getDGNParameters().getFile();
115
                resource = this.createResource(
116
                                FileResource.NAME,
117
                                new Object[] { file.getAbsolutePath() }
118
                        );
119

    
120
                resource.addConsumer(this);
121

    
122
                this.projection = this.getDGNParameters().getCRS();
123

    
124

    
125
                try {
126
                        legendBuilder = (LegendBuilder) this.invokeDynMethod(
127
                                        LegendBuilder.DYNMETHOD_BUILDER_NAME, null);
128
                } catch (DynMethodException e) {
129
                        legendBuilder = null;
130
                } catch (Exception e) {
131
                        throw new InitializeException(e);
132
                }
133

    
134
                this.initializeFeatureTypes();
135

    
136
        }
137

    
138
        private DGNStoreParameters getDGNParameters() {
139
                return (DGNStoreParameters) this.getParameters();
140
        }
141

    
142

    
143
        public String getName() {
144
                return NAME;
145
        }
146

    
147
        public boolean allowWrite() {
148
                return true;
149
        }
150

    
151
        public Object getLegend() throws OpenException {
152
                this.open();
153
                if (legendBuilder == null) {
154
                        return null;
155
                }
156
                return legendBuilder.getLegend();
157
        }
158

    
159
        public Object getLabeling() throws OpenException {
160
                this.open();
161
                if (legendBuilder == null) {
162
                        return null;
163
                }
164
                return legendBuilder.getLabeling();
165
        }
166

    
167
        private class DGNData {
168
                public List data = null;
169
                public FeatureType defaultFType = null;
170
                public List fTypes = null;
171
                public Envelope envelope = null;
172
                public IProjection projection;
173
                public LegendBuilder legendBuilder;
174
                public Envelope getEnvelopeCopy() throws CreateEnvelopeException {
175
                        if (envelope == null) {
176
                                return null;
177
                        }
178
                        Envelope newEnvelope;
179
                        if (envelope.getDimension() == 2) {
180
                                newEnvelope = geomManager.createEnvelope(SUBTYPES.GEOM2D);
181
                        } else {
182
                                newEnvelope = geomManager.createEnvelope(SUBTYPES.GEOM3D);
183

    
184
                        }
185
                        newEnvelope.setLowerCorner(envelope.getLowerCorner());
186
                        newEnvelope.setUpperCorner(envelope.getUpperCorner());
187
                        return newEnvelope;
188
                }
189
        }
190

    
191
        public void open() throws OpenException {
192
                if (this.data != null) {
193
                        return;
194
                }
195
                try {
196
                        getResource().execute(new ResourceAction() {
197
                                public Object run() throws Exception {
198
                                        FeatureStoreProviderServices store = getStoreServices();
199
                                        DGNData DGNData = null;
200
                                        if (resource.getData() != null) {
201
                                                DGNData =
202
                                                                (DGNData) ((Map) resource.getData()).get(projection.getAbrev()); // OJO
203
                                                // no es del todo correcto (puede llevar reproyeccion)
204
                                        } else {
205
                                                resource.setData(new HashMap());
206
                                        }
207
                                        if (DGNData == null) {
208
                                                DGNData = new DGNData();
209
                                                DGNData.data = new ArrayList();
210
                                                data = DGNData.data;
211
                                                counterNewsOIDs = 0;
212
                                                Reader reader =
213
                                                                new Reader().initialice(getMemoryProvider(),
214
                                                                                new File((String) resource.get()),
215
                                                                                projection, legendBuilder);
216
                                                reader.begin(store);
217
                                                DGNData.defaultFType =
218
                                                                reader.getDefaultType().getNotEditableCopy();
219
                                                List types = new ArrayList();
220
                                                Iterator it = reader.getTypes().iterator();
221
                                                EditableFeatureType fType;
222
                                                while (it.hasNext()) {
223
                                                        fType = (EditableFeatureType) it.next();
224
                                                        if (fType.getId().equals(
225
                                                                        DGNData.defaultFType.getId())) {
226
                                                                types.add(DGNData.defaultFType);
227
                                                        } else {
228
                                                                types.add(fType.getNotEditableCopy());
229
                                                        }
230
                                                }
231
                                                DGNData.fTypes = types;
232

    
233
                                                resource.notifyOpen();
234
                                                store.setFeatureTypes(DGNData.fTypes,
235
                                                                DGNData.defaultFType);
236
                                                reader.load();
237
                                                // envelope = reader.getEnvelope();
238

    
239
                                                DGNData.envelope = reader.getEnvelope();
240

    
241
                                                DGNData.legendBuilder = legendBuilder;
242

    
243
                                                DGNData.projection = projection;
244

    
245
                                                reader.end();
246
                                                resource.notifyClose();
247
                                                ((Map) resource.getData()).put(projection.getAbrev(),
248
                                                                DGNData); // OJO la
249
                                                // reproyeccion
250
                                        }
251

    
252
                                        data = DGNData.data;
253
                                        store.setFeatureTypes(DGNData.fTypes, DGNData.defaultFType);
254
                                        legendBuilder = DGNData.legendBuilder;
255
                                        setDynValue("Envelope", DGNData.getEnvelopeCopy());
256
                                        setDynValue("DefaultSRS", projection.getAbrev());
257
                                        counterNewsOIDs = data.size();
258
                                        return null;
259
                                }
260
                        });
261
                } catch (Exception e) {
262
                        data = null;
263
                        try {
264
                                throw new OpenException(resource.getName(), e);
265
                        } catch (AccessResourceException e1) {
266
                                throw new OpenException(getName(), e);
267
                        }
268
                }
269
        }
270

    
271

    
272
        public DataServerExplorer getExplorer() throws ReadException {
273
                DataManager manager = DALLocator.getDataManager();
274
                FilesystemServerExplorerParameters params;
275
                try {
276
                        params = (FilesystemServerExplorerParameters) manager
277
                                .createServerExplorerParameters(FilesystemServerExplorer.NAME);
278
                        params.setRoot(this.getDGNParameters().getFile().getParent());
279
                        return manager.openServerExplorer(FilesystemServerExplorer.NAME, params);
280
                } catch (DataException e) {
281
                        throw new ReadException(this.getName(), e);
282
                } catch (ValidateDataParametersException e) {
283
                        throw new ReadException(this.getName(), e);
284
                }
285

    
286
        }
287

    
288

    
289

    
290
        public void performChanges(Iterator deleteds, Iterator inserteds, Iterator updateds, Iterator originalFeatureTypesUpdated) throws PerformEditingException {
291
                // FIXME Exception
292
                throw new UnsupportedOperationException();
293
        }
294

    
295
        public class Reader {
296
                private File file;
297
//                private String fileName;
298
                private IProjection projection;
299
                private List types;
300
                private LegendBuilder leyendBuilder;
301
                private AbstractMemoryStoreProvider store;
302
                private Envelope envelope;
303

    
304
                public Reader initialice(AbstractMemoryStoreProvider store, File file,
305
                                IProjection projection,
306
                                LegendBuilder leyendBuilder) {
307
                        this.store = store;
308
                        this.file = file;
309
//                        this.fileName = file.getAbsolutePath();
310
                        this.projection = projection;
311
                        this.leyendBuilder = leyendBuilder;
312
                        if (leyendBuilder != null) {
313
                                leyendBuilder.initialize(store);
314
                        }
315
                        return this;
316
                }
317

    
318
                public Envelope getEnvelope() {
319
                        return this.envelope;
320
                }
321

    
322
                public void begin(FeatureStoreProviderServices store) {
323

    
324
                        EditableFeatureType featureType = store.createFeatureType();
325

    
326
                        featureType.setHasOID(true);
327

    
328
                        ID_FIELD_ID = featureType.add(NAME_FIELD_ID, DataTypes.INT)
329
                                        .setDefaultValue(Integer.valueOf(0))
330
                                .getIndex();
331

    
332
                        // FIXME: Cual es el size y el valor por defecto para Entity ?
333
                        ID_FIELD_ENTITY = featureType.add(NAME_FIELD_ENTITY,
334
                                        DataTypes.STRING, 100)
335
                                        .setDefaultValue("")
336
                                        .getIndex();
337

    
338
                        // FIXME: Cual es el size de Layer ?
339
                        ID_FIELD_LAYER = featureType.add(NAME_FIELD_LAYER,
340
                                        DataTypes.STRING, 100)
341
                                        .setDefaultValue(
342
                                        "default").getIndex();
343

    
344
                        ID_FIELD_COLOR = featureType.add(NAME_FIELD_COLOR,
345
                                        DataTypes.INT)
346
                                        .setDefaultValue(
347
                                        Integer.valueOf(0)).getIndex();
348

    
349
//                        ID_FIELD_ELEVATION = featureType.add(NAME_FIELD_ELEVATION,
350
//                                        DataTypes.DOUBLE)
351
//                                        .setDefaultValue(
352
//                                        Double.valueOf(0)).getIndex();
353
//
354
//                        ID_FIELD_THICKNESS = featureType.add(NAME_FIELD_THICKNESS,
355
//                                        DataTypes.DOUBLE)
356
//                                        .setDefaultValue(
357
//                                        Double.valueOf(0)).getIndex();
358
//
359
                        // FIXME: Cual es el size de Text ?
360
                        ID_FIELD_TEXT = featureType.add(NAME_FIELD_TEXT,
361
                                        DataTypes.STRING, 100)
362
                                        .setDefaultValue("")
363
                                        .getIndex();
364

    
365
                        ID_FIELD_HEIGHTTEXT = featureType.add(NAME_FIELD_HEIGHTTEXT,
366
                                        DataTypes.DOUBLE).setDefaultValue(
367
                                        Double.valueOf(10)).getIndex();
368

    
369
                        ID_FIELD_ROTATIONTEXT = featureType.add(NAME_FIELD_ROTATIONTEXT,
370
                                        DataTypes.DOUBLE).setDefaultValue(
371
                                        Double.valueOf(0)).getIndex();
372

    
373

    
374
                        EditableFeatureAttributeDescriptor attr = featureType.add(
375
                                        NAME_FIELD_GEOMETRY, DataTypes.GEOMETRY);
376
                        attr.setSRS(this.projection);
377
                        attr.setGeometryType(Geometry.TYPES.GEOMETRY);
378
                        attr.setGeometrySubType(Geometry.SUBTYPES.GEOM2DZ);
379
//                        ID_FIELD_GEOMETRY = attr.getIndex();
380

    
381
                        featureType.setDefaultGeometryAttributeName(NAME_FIELD_GEOMETRY);
382

    
383

    
384
                        // FIXME: Parece que el DGN puede tener mas atributos opcionales.
385
                        // Habria que ver de pillarlos ?
386

    
387
                        types = new ArrayList();
388
                        types.add(featureType);
389

    
390
                        if (leyendBuilder != null) {
391
                                leyendBuilder.begin();
392
                        }
393

    
394
                }
395

    
396
                public void end() {
397
                        if (leyendBuilder != null) {
398
                                leyendBuilder.end();
399
                        }
400
                }
401

    
402
                public List getTypes() {
403
                        return types;
404
                }
405

    
406
                public EditableFeatureType getDefaultType() {
407
                        return (EditableFeatureType) types.get(0);
408
                }
409

    
410
//                private Double toDouble(String value) {
411
//                        if (value == null) {
412
//                                return Double.valueOf(0);
413
//                        }
414
//                        return Double.valueOf(value);
415
//                }
416

    
417
                public void load() throws DataException {
418

    
419
                        this.envelope = null;
420

    
421
                        DGNReader dgnReader = new DGNReader(file.getAbsolutePath());
422

    
423
                        FeatureType type = getDefaultType().getNotEditableCopy();
424
                        int fTypeSize = type.size();
425
                        Object[] auxRow = new Object[fTypeSize];
426
                        Object[] cellRow = new Object[fTypeSize];
427
                        Object[] complexRow = new Object[fTypeSize];
428

    
429
                        boolean bElementoCompuesto = false;
430
                        boolean bEsPoligono = false;
431
                        boolean bInsideCell = false;
432
                        boolean bFirstHoleEntity = false;
433
                        boolean bConnect = false; // Se usa para que los pol?gonos cierren
434
                                                                                // bien cuando son formas compuestas
435
//                        int contadorSubElementos = 0;
436
//                        int numSubElementos = 0;
437
                        int complex_index_fill_color = -1;
438
                        int nClass; // Para filtrar los elementos de construcci?n, etc.
439
                        GeneralPathX elementoCompuesto = new GeneralPathX(
440
                                        GeneralPathX.WIND_EVEN_ODD);
441

    
442
                        for (int id = 0; id < dgnReader.getNumEntities(); id++) {
443
                                // System.out.println("Elemento " + id + " de " +
444
                                // dgnReader.getNumEntities());
445
                                dgnReader.DGNGotoElement(id);
446

    
447
                                DGNElemCore elemento = dgnReader.DGNReadElement();
448
                                nClass = 0;
449
                                auxRow[ID_FIELD_HEIGHTTEXT] = new Double(0);
450
                                auxRow[ID_FIELD_ROTATIONTEXT] = new Double(0);
451
                                auxRow[ID_FIELD_TEXT] = null;
452

    
453
                                if (elemento.properties != 0) {
454
                                        nClass = elemento.properties & DGNFileHeader.DGNPF_CLASS;
455
                                }
456

    
457
                                if ((elemento != null) && (elemento.deleted == 0)
458
                                                && (nClass == 0)) // Leer un elemento
459
                                {
460

    
461
                                        // if ((elemento.element_id > 3800) && (elemento.element_id
462
                                        // < 3850))
463
                                        // dgnReader.DGNDumpElement(dgnReader.getInfo(),elemento,"");
464
                                        if ((elemento.stype == DGNFileHeader.DGNST_MULTIPOINT)
465
                                                        || (elemento.stype == DGNFileHeader.DGNST_ARC)
466
                                                        || (elemento.stype == DGNFileHeader.DGNST_CELL_HEADER)
467
                                                        || (elemento.stype == DGNFileHeader.DGNST_SHARED_CELL_DEFN)
468
                                                        || (elemento.stype == DGNFileHeader.DGNST_COMPLEX_HEADER)) {
469
                                                if (elemento.complex != 0) {
470
                                                        bElementoCompuesto = true;
471
                                                } else {
472
                                                        if (bElementoCompuesto) {
473
                                                                if (bInsideCell) {
474
                                                                        auxRow[ID_FIELD_ENTITY] = cellRow[ID_FIELD_ENTITY];
475
                                                                } else {
476
                                                                        auxRow = complexRow;
477
                                                                }
478

    
479
                                                                // System.err.println("Entidad compuesta. bInsideCell = "
480
                                                                // + bInsideCell + " auxRow = " +
481
                                                                // auxRow[ID_FIELD_ENTITY]);
482
                                                                // addShape(new FPolyline2D(elementoCompuesto),
483
                                                                // auxRow);
484
                                                                addShape(createMultiCurve(elementoCompuesto),
485
                                                                                auxRow, type, dgnReader);
486

    
487
                                                                if (bEsPoligono) {
488
                                                                        if (complex_index_fill_color != -1) {
489
                                                                                auxRow[ID_FIELD_COLOR] = complex_index_fill_color;
490
                                                                        }
491

    
492
                                                                        addShape(
493
                                                                                        createMultiSurface(elementoCompuesto),
494
                                                                                        auxRow, type, dgnReader);
495
                                                                }
496

    
497
                                                                elementoCompuesto = new GeneralPathX(
498
                                                                                GeneralPathX.WIND_EVEN_ODD);
499
                                                        }
500

    
501
                                                        // System.err.println("Entidad simple");
502
                                                        bElementoCompuesto = false;
503
                                                        bEsPoligono = false;
504
                                                        bConnect = false;
505

    
506
                                                        // elementoCompuesto = new GeneralPathX();
507
                                                        bInsideCell = false;
508
                                                }
509
                                        }
510

    
511
                                        switch (elemento.stype) {
512
                                        case DGNFileHeader.DGNST_SHARED_CELL_DEFN:
513
                                                bInsideCell = true;
514
                                                cellRow[ID_FIELD_ID] = elemento.element_id;
515
                                                cellRow[ID_FIELD_LAYER] = String
516
                                                                .valueOf(elemento.level);
517
                                                cellRow[ID_FIELD_COLOR] = elemento.color;
518
                                                cellRow[ID_FIELD_ENTITY] = "Shared Cell";
519

    
520
                                                break;
521

    
522
                                        case DGNFileHeader.DGNST_CELL_HEADER:
523
                                                bInsideCell = true;
524

    
525
//                                                DGNElemCellHeader psCellHeader = (DGNElemCellHeader) elemento;
526
                                                cellRow[ID_FIELD_ID] = elemento.element_id;
527
                                                cellRow[ID_FIELD_LAYER] = String
528
                                                                .valueOf(elemento.level);
529
                                                cellRow[ID_FIELD_COLOR] = elemento.color;
530
                                                cellRow[ID_FIELD_ENTITY] = "Cell";
531
                                                complex_index_fill_color = dgnReader
532
                                                                .DGNGetShapeFillInfo(elemento);
533

    
534
                                                // System.err.println("Cell Header " +
535
                                                // complex_index_fill_color);
536
                                                break;
537

    
538
                                        case DGNFileHeader.DGNST_COMPLEX_HEADER:
539

    
540
                                                // bElementoCompuesto = true;
541
                                                // System.err.println("Complex Header");
542
//                                                contadorSubElementos = 0;
543

    
544
                                                DGNElemComplexHeader psComplexHeader = (DGNElemComplexHeader) elemento;
545
//                                                numSubElementos = psComplexHeader.numelems;
546
                                                complexRow[ID_FIELD_ID] = elemento.element_id;
547
                                                complexRow[ID_FIELD_LAYER] = String
548
                                                                .valueOf(elemento.level);
549
                                                complexRow[ID_FIELD_COLOR] = elemento.color;
550
                                                complexRow[ID_FIELD_ENTITY] = "Complex";
551

    
552
                                                if (psComplexHeader.type == DGNFileHeader.DGNT_COMPLEX_SHAPE_HEADER) {
553
                                                        bEsPoligono = true;
554

    
555
                                                        // Si es un agujero, no conectamos con el anterior
556
                                                        if ((psComplexHeader.properties & 0x8000) != 0) {
557
                                                                bFirstHoleEntity = true;
558
                                                        } else {
559
                                                                // Miramos si tiene color de relleno
560
                                                                // complex_index_fill_color = -1;
561
                                                                // if (elemento.attr_bytes > 0) {
562
                                                                complex_index_fill_color = dgnReader
563
                                                                                .DGNGetShapeFillInfo(elemento);
564

    
565
                                                                // System.err.println("complex shape fill color = "
566
                                                                // + elemento.color);
567
                                                                // }
568
                                                        }
569

    
570
                                                        bConnect = true;
571
                                                } else {
572
                                                        bEsPoligono = false;
573
                                                        bConnect = false;
574
                                                }
575

    
576
                                                break;
577

    
578
                                        case DGNFileHeader.DGNST_MULTIPOINT:
579

    
580
                                                // OJO: Si lo que viene en este multipoint es un
581
                                                // elemento con type=11 (curve), se trata de una
582
                                                // "parametric
583
                                                // spline curve". La vamos a tratar como si no fuera
584
                                                // curva, pero seg?n la documentaci?n, los 2 primeros
585
                                                // puntos
586
                                                // y los 2 ?ltimos puntos definen "endpoint derivatives"
587
                                                // y NO se muestran.
588
                                                // TODAV?A HAY UN PEQUE?O FALLO CON EL FICHERO
589
                                                // dgn-sample.dgn, pero lo dejo por ahora.
590
                                                // Es posible que tenga que ver con lo de los arcos
591
                                                // (arco distorsionado), que
592
                                                // todav?a no est? metido.
593
                                                DGNElemMultiPoint psLine = (DGNElemMultiPoint) elemento;
594
                                                auxRow[ID_FIELD_ID] = elemento.element_id;
595
                                                auxRow[ID_FIELD_ENTITY] = "Multipoint";
596
                                                auxRow[ID_FIELD_LAYER] = String.valueOf(elemento.level);
597
                                                auxRow[ID_FIELD_COLOR] = elemento.color;
598

    
599
                                                if ((psLine.num_vertices == 2)
600
                                                                && (psLine.vertices[0].x == psLine.vertices[1].x)
601
                                                                && (psLine.vertices[0].y == psLine.vertices[1].y)) {
602
                                                        auxRow[ID_FIELD_ENTITY] = "Point";
603
                                                        addShape(
604
                                                                        createPoint3D(psLine.vertices[0].x,
605
                                                                                        psLine.vertices[0].y,
606
                                                                                        psLine.vertices[0].z), auxRow,
607
                                                                        type, dgnReader);
608
                                                } else {
609
                                                        GeneralPathX elShape = new GeneralPathX(
610
                                                                        GeneralPathX.WIND_EVEN_ODD);
611

    
612
                                                        if (psLine.type == DGNFileHeader.DGNT_CURVE) {
613
                                                                psLine.num_vertices = psLine.num_vertices - 4;
614

    
615
                                                                for (int aux_n = 0; aux_n < psLine.num_vertices; aux_n++) {
616
                                                                        psLine.vertices[aux_n] = psLine.vertices[aux_n + 2];
617
                                                                }
618
                                                        }
619

    
620
                                                        if ((psLine.type == DGNFileHeader.DGNT_SHAPE)
621
                                                                        && ((psLine.properties & 0x8000) != 0)) {
622
                                                                // Invertimos el orden porque es un agujero
623
                                                                elShape
624
                                                                                .moveTo(
625
                                                                                                psLine.vertices[psLine.num_vertices - 1].x,
626
                                                                                                psLine.vertices[psLine.num_vertices - 1].y);
627

    
628
                                                                for (int i = psLine.num_vertices - 2; i >= 0; i--) {
629
                                                                        elShape.lineTo(psLine.vertices[i].x,
630
                                                                                        psLine.vertices[i].y);
631
                                                                }
632
                                                        } else {
633
                                                                elShape.moveTo(psLine.vertices[0].x,
634
                                                                                psLine.vertices[0].y);
635

    
636
                                                                for (int i = 1; i < psLine.num_vertices; i++) {
637
                                                                        elShape.lineTo(psLine.vertices[i].x,
638
                                                                                        psLine.vertices[i].y);
639
                                                                }
640
                                                        }
641

    
642
                                                        if ((psLine.vertices[0].x == psLine.vertices[psLine.num_vertices - 1].x)
643
                                                                        && (psLine.vertices[0].y == psLine.vertices[psLine.num_vertices - 1].y)) {
644
                                                                // Lo a?adimos tambi?n como pol?gono
645
                                                                bEsPoligono = true;
646

    
647
                                                                // Miramos si tiene color de relleno
648
                                                                if (elemento.attr_bytes > 0) {
649
                                                                        elemento.color = dgnReader
650
                                                                                        .DGNGetShapeFillInfo(elemento);
651

    
652
                                                                        // System.err.println("fill color = " +
653
                                                                        // elemento.color);
654
                                                                        if (elemento.color != -1) {
655
                                                                                auxRow[ID_FIELD_COLOR] = elemento.color;
656
                                                                        }
657
                                                                }
658

    
659
                                                                if (elemento.complex == 0) {
660
                                                                        addShape(createSurface(elShape), auxRow,
661
                                                                                        type, dgnReader);
662
                                                                }
663
                                                        }
664

    
665
                                                        if (elemento.complex != 0) {
666
                                                                // Si es un agujero o
667
                                                                // es la primera entidad del agujero, lo
668
                                                                // a?adimos sin unir al anterior
669
                                                                if (bFirstHoleEntity
670
                                                                                || ((psLine.type == DGNFileHeader.DGNT_SHAPE) && ((psLine.properties & 0x8000) != 0))) {
671
                                                                        elementoCompuesto.append(elShape.getPathIterator(null), false);
672
                                                                        bFirstHoleEntity = false;
673
                                                                } else {
674
                                                                        elementoCompuesto.append(elShape.getPathIterator(null), bConnect);
675
                                                                }
676
                                                        } else {
677
                                                                addShape(createMultiCurve(elShape), auxRow,
678
                                                                                type, dgnReader);
679
                                                        }
680
                                                }
681

    
682
                                                break;
683

    
684
                                        case DGNFileHeader.DGNST_ARC:
685

    
686
                                                // dgnReader.DGNDumpElement(dgnReader.getInfo(),
687
                                                // elemento,"");
688
                                                DGNElemArc psArc = (DGNElemArc) elemento;
689

    
690
                                                // La definici?n de arco de MicroStation es distinta a
691
                                                // la de Java.
692
                                                // En el dgn el origin se entiende que es el centro del
693
                                                // arco,
694
                                                // y a la hora de crear un Arc2D las 2 primeras
695
                                                // coordenadas son
696
                                                // la esquina inferior izquierda del rect?ngulo que
697
                                                // rodea al arco.
698
                                                // 1.- Creamos la elipse sin rotaci?n.
699
                                                // 2.- Creamos el arco
700
                                                // 3.- Rotamos el resultado
701

    
702
                                                /*
703
                                                 * System.out.println("Arco con primari axis: " +
704
                                                 * psArc.primary_axis + " start angle: " +
705
                                                 * psArc.startang + " sweepang = " + psArc.sweepang);
706
                                                 * System.out.println("secondaria axis: " +
707
                                                 * psArc.secondary_axis + " rotation = " +
708
                                                 * psArc.rotation);
709
                                                 */
710
                                                AffineTransform mT = AffineTransform.getRotateInstance(
711
                                                                Math.toRadians(psArc.rotation), psArc.origin.x,
712
                                                                psArc.origin.y);
713

    
714
                                                // mT.preConcatenate(AffineTransform.getScaleInstance(100.0,100.0));
715
                                                Arc2D.Double elArco = new Arc2D.Double(psArc.origin.x
716
                                                                - psArc.primary_axis, psArc.origin.y
717
                                                                - psArc.secondary_axis,
718
                                                                2.0 * psArc.primary_axis,
719
                                                                2.0 * psArc.secondary_axis, -psArc.startang,
720
                                                                -psArc.sweepang, Arc2D.OPEN);
721

    
722
                                                // Ellipse2D.Double elArco = new
723
                                                // Ellipse2D.Double(psArc.origin.x - psArc.primary_axis,
724
                                                // psArc.origin.y - psArc.secondary_axis,2.0 *
725
                                                // psArc.primary_axis, 2.0 * psArc.secondary_axis);
726
                                                GeneralPathX elShapeArc = new GeneralPathX(elArco.getPathIterator(null));
727

    
728
                                                // Transformamos el GeneralPahtX porque si transformamos
729
                                                // elArco nos lo convierte
730
                                                // a GeneralPath y nos guarda las coordenadas en float,
731
                                                // con la correspondiente p?rdida de precisi?n
732
                                                elShapeArc.transform(mT);
733

    
734
                                                if (dgnReader.getInfo().dimension == 3) {
735
                                                        // Aqu? podr?amos hacer cosas con la coordenada Z
736
                                                }
737

    
738
                                                auxRow[ID_FIELD_ID] = elemento.element_id;
739
                                                auxRow[ID_FIELD_ENTITY] = "Arc";
740
                                                auxRow[ID_FIELD_LAYER] = String.valueOf(elemento.level);
741
                                                auxRow[ID_FIELD_COLOR] = elemento.color;
742

    
743
                                                /*
744
                                                 * Line2D.Double ejeMayor = new
745
                                                 * Line2D.Double(psArc.origin.x - psArc.primary_axis,
746
                                                 * psArc.origin.y, psArc.origin.x + psArc.primary_axis,
747
                                                 * psArc.origin.y);
748
                                                 *
749
                                                 * lyrLines.addShape(new
750
                                                 * FShape(FConstant.SHAPE_TYPE_POLYLINE, new
751
                                                 * GeneralPathX(ejeMayor)), auxRow);
752
                                                 */
753

    
754
                                                // lyrLines.addShape(new
755
                                                // FShape(FConstant.SHAPE_TYPE_POLYLINE, elShapeArc),
756
                                                // auxRow);
757
                                                if (elemento.complex != 0) {
758
                                                        // Esto es una posible fuente de fallos si detr?s de
759
                                                        // una
760
                                                        // elipse vienen m?s cosas pegadas. Deber?amos
761
                                                        // volver
762
                                                        // a conectar una vez pasada la elipse.
763
                                                        if (elemento.type == DGNFileHeader.DGNT_ELLIPSE) {
764
                                                                bConnect = false;
765
                                                        }
766

    
767
                                                        // SI LA ELIPSE ES UN AGUJERO, SE A?ADE SIN PEGAR
768
                                                        // Y EL ELEMENTO ES UN POLIGONO
769
                                                        if (bFirstHoleEntity
770
                                                                        || ((elemento.type == DGNFileHeader.DGNT_SHAPE) && ((elemento.properties & 0x8000) != 0))) {
771
                                                                elementoCompuesto.append(elShapeArc.getPathIterator(null), false);
772
                                                                bFirstHoleEntity = false;
773
                                                        } else {
774
                                                                elementoCompuesto.append(elShapeArc.getPathIterator(null), bConnect);
775
                                                        }
776
                                                } else {
777
                                                        addShape(createMultiCurve(elShapeArc), auxRow,
778
                                                                        type, dgnReader);
779

    
780
                                                        if (psArc.type == DGNFileHeader.DGNT_ELLIPSE) {
781
                                                                addShape(createSurface(elShapeArc), auxRow,
782
                                                                                type, dgnReader);
783
                                                        }
784
                                                }
785

    
786
                                                // System.err.println("Entra un Arco");
787
                                                break;
788

    
789
                                        case DGNFileHeader.DGNST_TEXT:
790

    
791
                                                DGNElemText psText = (DGNElemText) elemento;
792
                                                Geometry elShapeTxt = createPoint3D(psText.origin.x,
793
                                                                psText.origin.y, psText.origin.z);
794

    
795
                                                auxRow[ID_FIELD_ID] = elemento.element_id;
796
                                                auxRow[ID_FIELD_ENTITY] = "Text";
797
                                                auxRow[ID_FIELD_LAYER] = String.valueOf(elemento.level);
798
                                                auxRow[ID_FIELD_COLOR] = elemento.color;
799
                                                auxRow[ID_FIELD_HEIGHTTEXT] = psText.height_mult;
800
                                                auxRow[ID_FIELD_ROTATIONTEXT] = psText.rotation;
801
                                                auxRow[ID_FIELD_TEXT] = psText.string; // .trim();
802
                                                addShape(elShapeTxt, auxRow, type, dgnReader);
803

    
804
                                                // System.out.println("Rotaci?n texto: " +
805
                                                // psText.rotation + "Altura Texto = " + heightText);
806

    
807
                                                /*
808
                                                 * System.out.println("  origin=(" + psText.origin.x +
809
                                                 * ", " + psText.origin.y + ") rotation=" +
810
                                                 * psText.rotation + "\n" + "  font=" + psText.font_id +
811
                                                 * " just=" + psText.justification + "length_mult=" +
812
                                                 * psText.length_mult + " height_mult=" +
813
                                                 * psText.height_mult + "\n" + "  string =" + new
814
                                                 * String(psText.string).toString().trim() + "\n");
815
                                                 */
816
                                                break;
817

    
818
                                        /*
819
                                         * default:
820
                                         * dgnReader.DGNDumpElement(dgnReader.getInfo(),
821
                                         * elemento, "");
822
                                         */
823
                                        } // switch
824
                                } // if
825
                        } // for
826

    
827
                        if (bElementoCompuesto) {
828
                                if (bInsideCell) {
829
                                        auxRow = cellRow;
830
                                } else {
831
                                        auxRow = complexRow;
832
                                }
833

    
834
                                // System.err.println("Entidad compuesta. bInsideCell = " +
835
                                // bInsideCell + " auxRow = " + auxRow[ID_FIELD_ENTITY]);
836
                                addShape(createMultiCurve(elementoCompuesto), auxRow, type,
837
                                                dgnReader);
838

    
839
                                if (bEsPoligono) {
840
                                        if (complex_index_fill_color != -1) {
841
                                                auxRow[ID_FIELD_COLOR] = complex_index_fill_color;
842
                                        }
843

    
844
                                        addShape(createSurface(elementoCompuesto), auxRow, type,
845
                                                        dgnReader);
846
                                }
847
                        }
848

    
849
                }
850

    
851
                private Geometry createMultiSurface(GeneralPathX elementoCompuesto)
852
                                throws DataException {
853
                        try {
854
                                return geomManager.createMultiSurface(elementoCompuesto,
855
                                                SUBTYPES.GEOM2D);
856
                        } catch (CreateGeometryException e) {
857
                                throw new org.gvsig.fmap.dal.feature.exception.CreateGeometryException(
858
                                                e);
859
                        }
860

    
861
                }
862

    
863
                private Geometry createPoint3D(double x, double y, double z)
864
                                throws DataException {
865
                        Point point;
866
                        try {
867
                                // point = (Point) geomManager.create(TYPES.POINT,
868
                                // SUBTYPES.GEOM3D);
869
                                point = (Point) geomManager.create(TYPES.POINT,
870
                                                SUBTYPES.GEOM2DZ);
871
                        } catch (CreateGeometryException e) {
872
                                throw new org.gvsig.fmap.dal.feature.exception.CreateGeometryException(
873
                                                e);
874
                        }
875
                        point.setCoordinates(new double[] { x, y, z });
876

    
877
                        return point;
878
                }
879

    
880
                private void addShape(Geometry geometry, Object[] auxRow,
881
                                FeatureType type, DGNReader dgnReader) throws DataException {
882
                        FeatureProvider data = createFeatureProvider(type);
883
                        for (int i=0;i<type.size();i++){
884
                                data.set(i, auxRow[i]);
885
                        }
886
                        data.setDefaultGeometry(geometry);
887
                        addFeatureProvider(data);
888
                        if (this.envelope == null) {
889
                                this.envelope = geometry.getEnvelope();
890
                        } else {
891
                                this.envelope.add(geometry.getEnvelope());
892
                        }
893
                        if (this.leyendBuilder != null) {
894
                                this.leyendBuilder.process(data, dgnReader);
895
                        }
896
                }
897

    
898
                private Geometry createMultiCurve(GeneralPathX elementoCompuesto)
899
                                throws DataException {
900
                        try {
901
                                return geomManager.createMultiCurve(elementoCompuesto,
902
                                                SUBTYPES.GEOM2D);
903
                        } catch (CreateGeometryException e) {
904
                                throw new org.gvsig.fmap.dal.feature.exception.CreateGeometryException(
905
                                                e);
906
                        }
907
                }
908

    
909
                private Geometry createSurface(GeneralPathX elementoCompuesto)
910
                                throws DataException {
911
                        try {
912
                                return geomManager.createCurve(elementoCompuesto,
913
                                                SUBTYPES.GEOM2D);
914
                        } catch (CreateGeometryException e) {
915
                                throw new org.gvsig.fmap.dal.feature.exception.CreateGeometryException(
916
                                                e);
917
                        }
918

    
919
                }
920

    
921
        }
922

    
923
        public boolean closeResourceRequested(ResourceProvider resource) {
924
                return true;
925
        }
926

    
927
        public int getOIDType() {
928
                return DataTypes.LONG;
929
        }
930

    
931
        public boolean supportsAppendMode() {
932
                return false;
933
        }
934

    
935
        public void append(FeatureProvider featureProvider) {
936
                throw new UnsupportedOperationException();
937
        }
938

    
939
        public void beginAppend() {
940
                throw new UnsupportedOperationException();
941
        }
942

    
943
        public void endAppend() {
944
                throw new UnsupportedOperationException();
945
        }
946

    
947
        public Object createNewOID() {
948
                return new Long(counterNewsOIDs++);
949
        }
950

    
951
        protected void initializeFeatureTypes() throws InitializeException {
952
                try {
953
                        this.open();
954
                } catch (OpenException e) {
955
                        throw new InitializeException(this.getName(), e);
956
                }
957
        }
958

    
959
        public Envelope getEnvelope() throws DataException {
960
                this.open();
961
                return (Envelope) this.getDynValue("Envelope");
962
        }
963

    
964

    
965
        /*
966
         * (non-Javadoc)
967
         *
968
         * @see
969
         * org.gvsig.fmap.dal.resource.spi.ResourceConsumer#resourceChanged(org.
970
         * gvsig.fmap.dal.resource.spi.ResourceProvider)
971
         */
972
        public void resourceChanged(ResourceProvider resource) {
973
                this.getStoreServices().notifyChange(
974
                                DataStoreNotification.RESOURCE_CHANGED,
975
                                resource);
976
        }
977

    
978
        protected static void registerMetadataDefinition() throws MetadataException {
979
                MetadataManager manager = MetadataLocator.getMetadataManager();
980
                if( manager.getDefinition(METADATA_DEFINITION_NAME)==null ) {
981
                        DynStruct metadataDefinition = manager.addDefinition(
982
                                        METADATA_DEFINITION_NAME, 
983
                                        METADATA_DEFINITION_DESCRIPTION 
984
                        );
985
                        metadataDefinition.extend( manager.getDefinition(FeatureStore.METADATA_DEFINITION_NAME));
986
                }
987
        }
988

    
989
        public Object getSourceId() {
990
                return this.getDGNParameters().getFile();
991
        }
992

    
993
        public ResourceProvider getResource() {
994
                return resource;
995
        }
996

    
997
}