Statistics
| Revision:

root / org.gvsig.dgn / trunk / org.gvsig.dgn / org.gvsig.dgn.provider / src / main / java / org / gvsig / fmap / dal / store / dgn / DGNStoreProvider.java @ 87

History | View | Annotate | Download (80.1 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.BufferedWriter;
6
import java.io.File;
7
import java.io.FileWriter;
8
import java.io.IOException;
9
import java.util.ArrayList;
10
import java.util.Collections;
11
import java.util.Comparator;
12
import java.util.HashMap;
13
import java.util.Iterator;
14
import java.util.List;
15
import java.util.Map;
16
import java.util.logging.Level;
17
import java.util.regex.Pattern;
18
import org.apache.commons.io.IOUtils;
19
import org.apache.commons.lang3.StringUtils;
20

    
21
import org.cresques.cts.IProjection;
22
import org.gvsig.fmap.dal.DALLocator;
23
import org.gvsig.fmap.dal.DataManager;
24
import org.gvsig.fmap.dal.DataServerExplorer;
25
import org.gvsig.fmap.dal.DataStoreNotification;
26
import org.gvsig.fmap.dal.DataTypes;
27
import org.gvsig.fmap.dal.FileHelper;
28
import org.gvsig.fmap.dal.exception.DataException;
29
import org.gvsig.fmap.dal.exception.InitializeException;
30
import org.gvsig.fmap.dal.exception.OpenException;
31
import org.gvsig.fmap.dal.exception.ReadException;
32
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
33
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
34
import org.gvsig.fmap.dal.feature.EditableFeatureType;
35
import org.gvsig.fmap.dal.feature.FeatureType;
36
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
37
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
38
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices;
39
import org.gvsig.fmap.dal.feature.spi.memory.AbstractMemoryStoreProvider;
40
import org.gvsig.fmap.dal.resource.ResourceAction;
41
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
42
import org.gvsig.fmap.dal.resource.file.FileResource;
43
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
44
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
45
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorer;
46
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemServerExplorerParameters;
47
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
48
import org.gvsig.fmap.dal.store.dgn.lib.DGNElemArc;
49
import org.gvsig.fmap.dal.store.dgn.lib.DGNElemComplexHeader;
50
import org.gvsig.fmap.dal.store.dgn.lib.DGNElemCore;
51
import org.gvsig.fmap.dal.store.dgn.lib.DGNElemMultiPoint;
52
import org.gvsig.fmap.dal.store.dgn.lib.DGNElemText;
53
import org.gvsig.fmap.dal.store.dgn.lib.DGNFileHeader;
54
import org.gvsig.fmap.dal.store.dgn.lib.DGNPoint;
55
import org.gvsig.fmap.dal.store.dgn.lib.DGNReader;
56
import org.gvsig.fmap.geom.Geometry;
57
import org.gvsig.fmap.geom.GeometryLocator;
58
import org.gvsig.fmap.geom.GeometryManager;
59
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
60
import org.gvsig.fmap.geom.Geometry.TYPES;
61
import org.gvsig.fmap.geom.aggregate.MultiPoint;
62
import org.gvsig.fmap.geom.aggregate.MultiPrimitive;
63
import org.gvsig.fmap.geom.aggregate.MultiSurface;
64
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
65
import org.gvsig.fmap.geom.exception.CreateGeometryException;
66
import org.gvsig.fmap.geom.operation.GeometryOperationException;
67
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
68
import org.gvsig.fmap.geom.primitive.Curve;
69
import org.gvsig.fmap.geom.primitive.Envelope;
70
import org.gvsig.fmap.geom.primitive.GeneralPathX;
71
import org.gvsig.fmap.geom.primitive.OrientablePrimitive;
72
import org.gvsig.fmap.geom.primitive.Point;
73
import org.gvsig.fmap.geom.primitive.Primitive;
74
import org.gvsig.fmap.geom.primitive.Surface;
75
import org.gvsig.fmap.geom.type.GeometryType;
76
import org.gvsig.tools.dynobject.exception.DynMethodException;
77
import org.gvsig.tools.logger.FilteredLogger;
78
import org.slf4j.Logger;
79
import org.slf4j.LoggerFactory;
80

    
81
public class DGNStoreProvider extends AbstractMemoryStoreProvider implements
82
        ResourceConsumer {
83

    
84
    private static final Logger logger = LoggerFactory.getLogger(DGNStoreProvider.class);
85

    
86
    public static final String NAME = "DGN";
87
    public static final String DESCRIPTION = "DGN file";
88

    
89
    public static final String METADATA_DEFINITION_NAME = NAME;
90
    private static final String METADATA_DEFINITION_DESCRIPTION = "DGN File Store";
91

    
92
    public static final int LOAD_MODE_PLAIN = 0;
93
    public static final int LOAD_MODE_GROUP1 = 1;
94

    
95
    public static final int CROP_OPERATION_NONE = 0;
96
    private static final int CROP_OPERATION_CONTAINS = 1;
97
    private static final int CROP_OPERATION_COVERS = 2;
98
    private static final int CROP_OPERATION_COVEREDBY = 3;
99
    private static final int CROP_OPERATION_CROSSES = 4;
100
    private static final int CROP_OPERATION_DISJOINT = 5;
101
    private static final int CROP_OPERATION_INTERSECT = 6;
102
    private static final int CROP_OPERATION_OVERLAPS = 7;
103
    private static final int CROP_OPERATION_TOUCHES = 8;
104
    private static final int CROP_OPERATION_WITHIN = 9;
105

    
106
    private static final String NAME_FIELD_ID = "ID";
107
    private static final String NAME_FIELD_GEOMETRY = "Geometry";
108
    private static final String NAME_FIELD_TYPE = "Type";
109
    private static final String NAME_FIELD_STYPE = "SType";
110
    private static final String NAME_FIELD_ENTITY = "Entity";
111
    private static final String NAME_FIELD_LEVEL = "Layer";
112
    public static final String NAME_FIELD_COLOR = "Color";
113
    public static final String NAME_FIELD_FILLCOLOR = "FillColor";
114
    private static final String NAME_FIELD_ELEVATION = "Elevation";
115
    private static final String NAME_FIELD_WEIGHT = "Weight";
116
    public static final String NAME_FIELD_TEXT = "Text";
117
    public static final String NAME_FIELD_HEIGHTTEXT = "HeightText";
118
    public static final String NAME_FIELD_HEIGHTTEXTRAW = "HeightTextRaw";
119
    public static final String NAME_FIELD_ROTATIONTEXT = "Rotation";
120
    public static final String NAME_FIELD_STYLE = "Style";
121
    public static final String NAME_FIELD_GROUP = "Group";
122
    public static final String NAME_FIELD_ISSHAPE = "IsShape";
123
    public static final String NAME_FIELD_ISCOMPLEXSHAPEHEADER = "IsComplexShapeHeader";
124
    public static final String NAME_FIELD_ISHOLE = "IsHole";
125
    public static final String NAME_FIELD_ISCOMPLEX = "IsComplex";
126
    public static final String NAME_FIELD_PARENTID = "ParentId";
127
    public static final String NAME_FIELD_SCALE = "Scale";
128

    
129
    private int ID_FIELD_ID;
130
    private int ID_FIELD_TYPE;
131
    private int ID_FIELD_STYPE;
132
    private int ID_FIELD_ENTITY;
133
    private int ID_FIELD_LEVEL;
134
    private int ID_FIELD_COLOR;
135
    private int ID_FIELD_FILLCOLOR;
136
    private int ID_FIELD_ELEVATION;
137
    private int ID_FIELD_WEIGHT;
138
    private int ID_FIELD_TEXT;
139
    private int ID_FIELD_HEIGHTTEXT;
140
    private int ID_FIELD_HEIGHTTEXTRAW;
141
    private int ID_FIELD_ROTATIONTEXT;
142
    private int ID_FIELD_STYLE;
143
    private int ID_FIELD_GROUP;
144
    private int ID_FIELD_LAYER;
145
    private int ID_FIELD_ISCOMPLEXSHAPEHEADER;
146
    private int ID_FIELD_ISSHAPE;
147
    private int ID_FIELD_ISHOLE;
148
    private int ID_FIELD_ISCOMPLEX;
149
    private int ID_FIELD_PARENT;
150
    private int ID_FIELD_SCALE;
151
    private int ID_FIELD_GEOMETRY;
152
    private int MAX_FIELD_ID;
153

    
154
    private IProjection projection;
155
    private ResourceProvider resource;
156
    private LegendBuilder legendBuilder;
157

    
158
    private long counterNewsOIDs = 0;
159
    protected GeometryManager geomManager = GeometryLocator.getGeometryManager();
160

    
161
    private int groupByFieldIndex = -2;
162
    private Map<Object, FeatureProvider> groupedFeatures = null;
163

    
164
    DGNData dgndata = null;
165

    
166
    public DGNStoreProvider(DGNStoreParameters parameters,
167
            DataStoreProviderServices storeServices) throws InitializeException {
168
        super(
169
                parameters,
170
                storeServices,
171
                FileHelper.newMetadataContainer(METADATA_DEFINITION_NAME)
172
        );
173

    
174
        counterNewsOIDs = 0;
175
        //                projection = CRSFactory.getCRS(getParameters().getSRSID());
176

    
177
        File file = getDGNParameters().getFile();
178
        resource = this.createResource(
179
                FileResource.NAME,
180
                new Object[]{file.getAbsolutePath()}
181
        );
182

    
183
        resource.addConsumer(this);
184

    
185
        this.projection = this.getDGNParameters().getCRS();
186

    
187
        try {
188
            legendBuilder = (LegendBuilder) this.invokeDynMethod(
189
                    LegendBuilder.DYNMETHOD_BUILDER_NAME, null);
190
        } catch (DynMethodException e) {
191
            legendBuilder = null;
192
        } catch (Exception e) {
193
            throw new InitializeException(e);
194
        }
195

    
196
        this.initializeFeatureTypes();
197

    
198
    }
199

    
200
    private DGNStoreParameters getDGNParameters() {
201
        return (DGNStoreParameters) this.getParameters();
202
    }
203

    
204
    public String getProviderName() {
205
        return NAME;
206
    }
207

    
208
    public boolean allowWrite() {
209
        // not yet
210
        return false;
211
    }
212

    
213
    public Object getLegend() throws OpenException {
214
        this.open();
215
        if (legendBuilder == null) {
216
            return null;
217
        }
218
        return legendBuilder.getLegend();
219
    }
220

    
221
    public Object getLabeling() throws OpenException {
222
        this.open();
223
        if (legendBuilder == null) {
224
            return null;
225
        }
226
        return legendBuilder.getLabeling();
227
    }
228

    
229
    private class DGNData {
230

    
231
        public List data = null;
232
        public FeatureType defaultFType = null;
233
        public List fTypes = null;
234
        public Envelope envelope = null;
235
        public IProjection projection;
236
        public LegendBuilder legendBuilder;
237

    
238
        public Envelope getEnvelopeCopy() throws CreateEnvelopeException {
239
            if (envelope == null) {
240
                return null;
241
            }
242
            try {
243
                return (Envelope) envelope.clone();
244
            } catch (CloneNotSupportedException ex) {
245
                logger.warn("Can't clone envelope.",ex);
246
                return null;
247
            }
248
        }
249
    }
250

    
251
    public void open() throws OpenException {
252
        if (this.data != null) {
253
            return;
254
        }
255
        try {
256
            getResource().execute(new ResourceAction() {
257
                public Object run() throws Exception {
258
                    FeatureStoreProviderServices store = getStoreServices();
259
                    if (dgndata == null
260
                            && !(getDGNParameters().useReload() )) {
261
                        if (resource.getData() != null) {
262
                            dgndata = (DGNData) ((Map) resource.getData()).get(projection.getAbrev()); // OJO
263
                            // no es del todo correcto (puede llevar reproyeccion)
264
                        } else {
265
                            resource.setData(new HashMap());
266
                        }
267
                    }
268

    
269
                    if (dgndata == null) {
270
                        dgndata = new DGNData();
271
                        dgndata.data = new ArrayList();
272
                        data = dgndata.data;
273
                        counterNewsOIDs = 0;
274
                        Reader reader = new Reader().initialice(
275
                                getMemoryProvider(),
276
                                (File) resource.get(),
277
                                projection, legendBuilder);
278
                        reader.begin(store);
279
                        dgndata.defaultFType = reader.getDefaultType().getNotEditableCopy();
280
                        List types = new ArrayList();
281
                        Iterator it = reader.getTypes().iterator();
282
                        EditableFeatureType fType;
283
                        while (it.hasNext()) {
284
                            fType = (EditableFeatureType) it.next();
285
                            if (fType.getId().equals(
286
                                    dgndata.defaultFType.getId())) {
287
                                types.add(dgndata.defaultFType);
288
                            } else {
289
                                types.add(fType.getNotEditableCopy());
290
                            }
291
                        }
292
                        dgndata.fTypes = types;
293

    
294
                        resource.notifyOpen();
295
                        store.setFeatureTypes(dgndata.fTypes,
296
                                dgndata.defaultFType);
297
                        reader.load();
298
                        dgndata.envelope = reader.getEnvelope();
299
                        dgndata.legendBuilder = legendBuilder;
300
                        dgndata.projection = projection;
301
                        reader.end();
302
                        if (resource.getData() == null) {
303
                            resource.setData(new HashMap());
304
                        }
305
                        ((Map) resource.getData()).put(
306
                                projection.getAbrev(),
307
                                dgndata); // OJO la reproyeccion
308
                        resource.notifyClose();
309
                    }
310

    
311
                    data = dgndata.data;
312
                    store.setFeatureTypes(dgndata.fTypes, dgndata.defaultFType);
313
                    legendBuilder = dgndata.legendBuilder;
314
                    setDynValue("Envelope", dgndata.getEnvelopeCopy());
315
                    setDynValue("CRS", projection);
316
                    counterNewsOIDs = data.size();
317
                    return null;
318
                }
319
            });
320
        } catch (Exception e) {
321
            data = null;
322
            try {
323
                throw new OpenException(resource.getName(), e);
324
            } catch (AccessResourceException e1) {
325
                throw new OpenException(getProviderName(), e);
326
            }
327
        }
328
    }
329

    
330
    private void sortRows() {
331
        List rows = this.data;
332

    
333
        Collections.sort(rows, new Comparator<FeatureProvider>() {
334
            public int compare(FeatureProvider o1, FeatureProvider o2) {
335
                Geometry g1 = o1.getDefaultGeometry();
336
                Geometry g2 = o2.getDefaultGeometry();
337
                if (g1 == null) {
338
                    if (g2 == null) {
339
                        return 0;
340
                    } else {
341
                        return -1;
342
                    }
343
                } else if (g2 == null) {
344
                    return 1;
345
                }
346
                return g2.getType() - g1.getType();
347
            }
348
        });
349
    }
350

    
351
    public DataServerExplorer getExplorer() throws ReadException {
352
        DataManager manager = DALLocator.getDataManager();
353
        FilesystemServerExplorerParameters params;
354
        try {
355
            params = (FilesystemServerExplorerParameters) manager
356
                    .createServerExplorerParameters(FilesystemServerExplorer.NAME);
357
            params.setRoot(this.getDGNParameters().getFile().getParent());
358
            return manager.openServerExplorer(FilesystemServerExplorer.NAME, params);
359
        } catch (DataException e) {
360
            throw new ReadException(this.getProviderName(), e);
361
        } catch (ValidateDataParametersException e) {
362
            throw new ReadException(this.getProviderName(), e);
363
        }
364

    
365
    }
366

    
367
    public void performChanges(Iterator deleteds, Iterator inserteds, Iterator updateds, Iterator originalFeatureTypesUpdated) throws PerformEditingException {
368
        // FIXME Exception
369
        throw new UnsupportedOperationException();
370
    }
371

    
372
    public class Filter {
373

    
374
        private Pattern levelFilter = null;
375
        private Pattern colorFilter = null;
376
        private Pattern styleFilter = null;
377
        private Pattern weighFilter = null;
378
        private Pattern typeFilter = null;
379
        private Pattern stypeFilter = null;
380
        private Pattern idFilter = null;
381
        private Pattern groupFilter = null;
382
        private Pattern textFilter = null;
383
        private Point pointForCheckGeometries = null;
384
        private boolean hasfilter = false;
385
        private boolean skipCurruptGeometries = true;
386
        private int geometryTypeFilter = Geometry.TYPES.GEOMETRY;
387
        private int counter_exceptions = 0;
388
        private int cropOperationFilter;
389
        private Geometry cropFilter = null;
390

    
391
        Filter(DGNStoreParameters parameters, DGNReader dgnReader) {
392
            geometryTypeFilter = getDGNParameters().getGeometryTypeFilter();
393
            skipCurruptGeometries = getDGNParameters().skipCorruptGeometries();
394
            if ( !StringUtils.isBlank(parameters.getLevelFilter()) ) {
395
                this.levelFilter = Pattern.compile(parameters.getLevelFilter());
396
                this.hasfilter = true;
397
            }
398
            if (!StringUtils.isBlank(parameters.getColorFilter()) ) {
399
                colorFilter = Pattern.compile(parameters.getColorFilter());
400
                this.hasfilter = true;
401
            }
402
            if (!StringUtils.isBlank(parameters.getStyleFilter()) ) {
403
                styleFilter = Pattern.compile(parameters.getStyleFilter());
404
                this.hasfilter = true;
405
            }
406
            if (!StringUtils.isBlank(parameters.getWeightFilter()) ) {
407
                weighFilter = Pattern.compile(parameters.getWeightFilter());
408
                this.hasfilter = true;
409
            }
410
            if (!StringUtils.isBlank(parameters.getTypeFilter()) ) {
411
                this.typeFilter = Pattern.compile(parameters.getTypeFilter());
412
                this.hasfilter = true;
413
            }
414
            if (!StringUtils.isBlank(parameters.getSTypeFilter()) ) {
415
                this.stypeFilter = Pattern.compile(parameters.getSTypeFilter());
416
                this.hasfilter = true;
417
            }
418
            if (!StringUtils.isBlank(parameters.getWeightFilter()) ) {
419
                weighFilter = Pattern.compile(parameters.getWeightFilter());
420
                this.hasfilter = true;
421
            }
422
            if (!StringUtils.isBlank(parameters.getGroupFilter()) ) {
423
                groupFilter = Pattern.compile(parameters.getGroupFilter());
424
                this.hasfilter = true;
425
            }
426
            if (!StringUtils.isBlank(parameters.getIDFilter()) ) {
427
                idFilter = Pattern.compile(parameters.getIDFilter());
428
                this.hasfilter = true;
429
            }
430
            if (!StringUtils.isBlank(parameters.getTextFilter()) ) {
431
                textFilter = Pattern.compile(parameters.getTextFilter());
432
                this.hasfilter = true;
433
            }
434
            if (this.geometryTypeFilter != Geometry.TYPES.GEOMETRY) {
435
                this.hasfilter = true;
436
            }
437
            this.cropFilter = getDGNParameters().getCropFilter();
438
            if (this.cropFilter != null) {
439
                this.hasfilter = true;
440
            }
441
            this.cropOperationFilter = getDGNParameters().getCropOperationFilter();
442
            if (this.cropOperationFilter == CROP_OPERATION_NONE) {
443
                this.cropFilter = null;
444
            }
445
            this.pointForCheckGeometries = null;
446
            if (skipCurruptGeometries) {
447
                try {
448
                    if (dgnReader.getInfo().dimension == 3) {
449
                        this.pointForCheckGeometries = geomManager.createPoint(1, 1, Geometry.SUBTYPES.GEOM3D);
450
                        this.pointForCheckGeometries.setCoordinateAt(2, 1);
451
                    } else {
452
                        this.pointForCheckGeometries = geomManager.createPoint(1, 1, Geometry.SUBTYPES.GEOM2D);
453
                    }
454
                } catch (Exception ex) {
455
                    this.pointForCheckGeometries = null;
456
                }
457
            }
458
        }
459

    
460
        private boolean match(Pattern exp, Object value) {
461
            if (exp == null) {
462
                return true;
463
            }
464
            if (value == null) {
465
                return false;
466
            }
467
            return exp.matcher(value.toString()).matches();
468
        }
469

    
470
        public boolean accept(FeatureProvider data) {
471

    
472
            if (!this.hasfilter) {
473
                return true;
474
            }
475

    
476
            Geometry geometry = data.getDefaultGeometry();
477
            if (this.pointForCheckGeometries != null) {
478
                if (geometry != null) {
479
                    try {
480
                        this.pointForCheckGeometries.intersects(geometry);
481
                    } catch (Exception ex) {
482
                        // Skip geometries with problems
483
                        data.setDefaultGeometry(null);
484
                        geometry = null;
485
                    }
486
                }
487
            }
488

    
489
            try {
490
                if (!match(levelFilter, data.get(ID_FIELD_LEVEL))) {
491
                    return false;
492
                }
493
                if (!match(colorFilter, data.get(ID_FIELD_COLOR))) {
494
                    return false;
495
                }
496
                if (!match(styleFilter, data.get(ID_FIELD_STYLE))) {
497
                    return false;
498
                }
499
                if (!match(weighFilter, data.get(ID_FIELD_WEIGHT))) {
500
                    return false;
501
                }
502
                if (!match(typeFilter, data.get(ID_FIELD_TYPE))) {
503
                    return false;
504
                }
505
                if (!match(stypeFilter, data.get(ID_FIELD_STYPE))) {
506
                    return false;
507
                }
508
                if (!match(groupFilter, data.get(ID_FIELD_GROUP))) {
509
                    return false;
510
                }
511
                if (!match(idFilter, data.get(ID_FIELD_ID))) {
512
                    return false;
513
                }
514
                if (!match(textFilter, data.get(ID_FIELD_TEXT))) {
515
                    return false;
516
                }
517

    
518
                if (geometry != null) {
519
                    if (geometryTypeFilter != Geometry.TYPES.GEOMETRY) {
520
                        GeometryType geomtype = geometry.getGeometryType();
521
                        switch (geometryTypeFilter) {
522
                            case Geometry.TYPES.POINT:
523
                                if (!geomtype.isTypeOf(Geometry.TYPES.POINT)
524
                                        && !geomtype.isTypeOf(Geometry.TYPES.MULTIPOINT)) {
525
                                    return false;
526
                                }
527
                                break;
528
                            case Geometry.TYPES.CURVE:
529
                                if (!geomtype.isTypeOf(Geometry.TYPES.CURVE)
530
                                        && !geomtype.isTypeOf(Geometry.TYPES.MULTICURVE)) {
531
                                    return false;
532
                                }
533
                                break;
534
                            case Geometry.TYPES.SURFACE:
535
                                if (!geomtype.isTypeOf(Geometry.TYPES.SURFACE)
536
                                        && !geomtype.isTypeOf(Geometry.TYPES.MULTISURFACE)) {
537
                                    return false;
538
                                }
539
                                break;
540
                            default:
541
                                break;
542
                        }
543
                    }
544
                    if (this.cropFilter != null) {
545
                        switch (this.cropOperationFilter) {
546
                            case CROP_OPERATION_CONTAINS:
547
                                if (!this.cropFilter.contains(geometry)) {
548
                                    return false;
549
                                }
550
                                break;
551
                            case CROP_OPERATION_COVEREDBY:
552
                                if (!this.cropFilter.coveredBy(geometry)) {
553
                                    return false;
554
                                }
555
                                break;
556
                            case CROP_OPERATION_COVERS:
557
                                if (!this.cropFilter.covers(geometry)) {
558
                                    return false;
559
                                }
560
                                break;
561
                            case CROP_OPERATION_CROSSES:
562
                                if (!this.cropFilter.crosses(geometry)) {
563
                                    return false;
564
                                }
565
                                break;
566
                            case CROP_OPERATION_DISJOINT:
567
                                if (!this.cropFilter.disjoint(geometry)) {
568
                                    return false;
569
                                }
570
                                break;
571
                            case CROP_OPERATION_INTERSECT:
572
                                if (!this.cropFilter.intersects(geometry)) {
573
                                    return false;
574
                                }
575
                                break;
576
                            case CROP_OPERATION_OVERLAPS:
577
                                if (!this.cropFilter.overlaps(geometry)) {
578
                                    return false;
579
                                }
580
                                break;
581
                            case CROP_OPERATION_TOUCHES:
582
                                if (!this.cropFilter.touches(geometry)) {
583
                                    return false;
584
                                }
585
                                break;
586
                            case CROP_OPERATION_WITHIN:
587
                                if (!this.cropFilter.within(geometry)) {
588
                                    return false;
589
                                }
590
                                break;
591
                        }
592
                    }
593
                }
594
            } catch (Exception ex) {
595
                if (++counter_exceptions < 10) {
596
                    logger.warn("Can't filter data, accept it.", ex);
597
                } else if (counter_exceptions == 10) {
598
                    logger.warn("Can't filter data, accept it.", ex);
599
                    logger.warn("Too many exceptions, dont show more.");
600
                }
601
                return true;
602
            }
603
            return true;
604
        }
605

    
606
    }
607

    
608
    public class Reader {
609

    
610
        private File file;
611
        private IProjection projection;
612
        private List types;
613
        private LegendBuilder leyendBuilder;
614
        private AbstractMemoryStoreProvider store;
615
        private Envelope envelope;
616
        private Filter filter = null;
617

    
618
        public Reader initialice(AbstractMemoryStoreProvider store, File file,
619
                IProjection projection,
620
                LegendBuilder leyendBuilder) {
621
            this.store = store;
622
            this.file = file;
623
            this.projection = projection;
624
            this.leyendBuilder = leyendBuilder;
625
            if (leyendBuilder != null) {
626
                leyendBuilder.initialize(store);
627
            }
628
            return this;
629
        }
630

    
631
        public Envelope getEnvelope() {
632
            return this.envelope;
633
        }
634

    
635
        public void begin(FeatureStoreProviderServices store) {
636

    
637
            EditableFeatureType featureType = store.createFeatureType(getName());
638

    
639
            featureType.setHasOID(true);
640

    
641
            ID_FIELD_ID = featureType.add(NAME_FIELD_ID, DataTypes.INT)
642
                    .setDefaultValue(Integer.valueOf(0))
643
                    .getIndex();
644

    
645
            ID_FIELD_PARENT = featureType.add(NAME_FIELD_PARENTID, DataTypes.INT)
646
                    .setDefaultValue(Integer.valueOf(0))
647
                    .getIndex();
648

    
649
            // FIXME: Cual es el size y el valor por defecto para Entity ?
650
            ID_FIELD_ENTITY = featureType.add(NAME_FIELD_ENTITY, DataTypes.STRING, 100)
651
                    .setDefaultValue("")
652
                    .getIndex();
653

    
654
            // FIXME: Cual es el size de Layer ?
655
            ID_FIELD_LEVEL = featureType.add(NAME_FIELD_LEVEL, DataTypes.STRING, 100)
656
                    .setDefaultValue("default")
657
                    .getIndex();
658
            ID_FIELD_LAYER = ID_FIELD_LEVEL;
659

    
660
            ID_FIELD_COLOR = featureType.add(NAME_FIELD_COLOR, DataTypes.INT)
661
                    .setDefaultValue(Integer.valueOf(0))
662
                    .getIndex();
663

    
664
            // FIXME: Cual es el size de Text ?
665
            ID_FIELD_TEXT = featureType.add(NAME_FIELD_TEXT, DataTypes.STRING, 100)
666
                    .setDefaultValue("")
667
                    .getIndex();
668

    
669
            ID_FIELD_HEIGHTTEXT = featureType.add(NAME_FIELD_HEIGHTTEXT, DataTypes.DOUBLE)
670
                    .setDefaultValue(Double.valueOf(10))
671
                    .getIndex();
672

    
673
            ID_FIELD_HEIGHTTEXTRAW = featureType.add(NAME_FIELD_HEIGHTTEXTRAW, DataTypes.DOUBLE)
674
                    .setDefaultValue(Double.valueOf(10))
675
                    .getIndex();
676

    
677
            ID_FIELD_ROTATIONTEXT = featureType.add(NAME_FIELD_ROTATIONTEXT, DataTypes.DOUBLE)
678
                    .setDefaultValue(Double.valueOf(0))
679
                    .getIndex();
680

    
681
            ID_FIELD_TYPE = featureType.add(NAME_FIELD_TYPE, DataTypes.INT)
682
                    .setDefaultValue(Integer.valueOf(0))
683
                    .getIndex();
684

    
685
            ID_FIELD_STYPE = featureType.add(NAME_FIELD_STYPE, DataTypes.INT)
686
                    .setDefaultValue(Integer.valueOf(0))
687
                    .getIndex();
688

    
689
            ID_FIELD_FILLCOLOR = featureType.add(NAME_FIELD_FILLCOLOR, DataTypes.INT)
690
                    .setDefaultValue(Integer.valueOf(0))
691
                    .getIndex();
692

    
693
            ID_FIELD_STYLE = featureType.add(NAME_FIELD_STYLE, DataTypes.INT)
694
                    .setDefaultValue(Integer.valueOf(0))
695
                    .getIndex();
696

    
697
            ID_FIELD_ELEVATION = featureType.add(NAME_FIELD_ELEVATION, DataTypes.DOUBLE)
698
                    .setDefaultValue(Double.valueOf(0))
699
                    .getIndex();
700

    
701
            ID_FIELD_WEIGHT = featureType.add(NAME_FIELD_WEIGHT, DataTypes.DOUBLE)
702
                    .setDefaultValue(Double.valueOf(0))
703
                    .getIndex();
704

    
705
            ID_FIELD_GROUP = featureType.add(NAME_FIELD_GROUP, DataTypes.INT)
706
                    .setDefaultValue(Integer.valueOf(0))
707
                    .getIndex();
708

    
709
            ID_FIELD_ISSHAPE = featureType.add(NAME_FIELD_ISSHAPE, DataTypes.BOOLEAN)
710
                    .setDefaultValue(Boolean.FALSE)
711
                    .getIndex();
712

    
713
            ID_FIELD_ISCOMPLEXSHAPEHEADER = featureType.add(NAME_FIELD_ISCOMPLEXSHAPEHEADER, DataTypes.BOOLEAN)
714
                    .setDefaultValue(Boolean.FALSE)
715
                    .getIndex();
716

    
717
            ID_FIELD_ISHOLE = featureType.add(NAME_FIELD_ISHOLE, DataTypes.BOOLEAN)
718
                    .setDefaultValue(Boolean.FALSE)
719
                    .getIndex();
720

    
721
            ID_FIELD_ISCOMPLEX = featureType.add(NAME_FIELD_ISCOMPLEX, DataTypes.BOOLEAN)
722
                    .setDefaultValue(Boolean.FALSE)
723
                    .getIndex();
724

    
725
            ID_FIELD_SCALE = featureType.add(NAME_FIELD_SCALE, DataTypes.INT)
726
                    .setDefaultValue(Integer.valueOf(0))
727
                    .getIndex();
728

    
729
            EditableFeatureAttributeDescriptor attr = featureType.add(NAME_FIELD_GEOMETRY, DataTypes.GEOMETRY);
730
            attr.setSRS(this.projection);
731
            int geometryTypeFilter = getDGNParameters().getGeometryTypeFilter();
732
            attr.setGeometryType(geometryTypeFilter);
733
            attr.setGeometrySubType(Geometry.SUBTYPES.GEOM3D);
734
            ID_FIELD_GEOMETRY = attr.getIndex();
735

    
736
            featureType.setDefaultGeometryAttributeName(NAME_FIELD_GEOMETRY);
737

    
738
            MAX_FIELD_ID = featureType.size() - 1;
739

    
740
            types = new ArrayList();
741
            types.add(featureType);
742

    
743
            if (leyendBuilder != null) {
744
                leyendBuilder.begin();
745
            }
746

    
747
        }
748

    
749
        public void end() {
750
            if (leyendBuilder != null) {
751
                leyendBuilder.end();
752
            }
753
        }
754

    
755
        public List getTypes() {
756
            return types;
757
        }
758

    
759
        public EditableFeatureType getDefaultType() {
760
            return (EditableFeatureType) types.get(0);
761
        }
762

    
763
//                private Double toDouble(String value) {
764
//                        if (value == null) {
765
//                                return Double.valueOf(0);
766
//                        }
767
//                        return Double.valueOf(value);
768
//                }
769
        public void load() throws DataException, CreateEnvelopeException {
770
            switch (getDGNParameters().getLoadMode()) {
771
                case LOAD_MODE_PLAIN:
772
                default:
773
                    load_plain();
774
                    break;
775
                case LOAD_MODE_GROUP1:
776
                    load_group1();
777
                    break;
778
            }
779
        }
780

    
781
        public void load_plain() throws DataException {
782

    
783
            FileWriter xmlfw = null;
784
            BufferedWriter xmlbfw = null;
785

    
786
            this.envelope = null;
787

    
788
            boolean ignoreZs = getDGNParameters().ignoreZs();
789
            boolean useZAsElevation = getDGNParameters().useZAsElevation();
790
            boolean applyRoundToElevation = getDGNParameters().getApplyRoundToElevation();
791
            double elevationFactor = getDGNParameters().geElevationFactor();
792
                    
793
            try {
794
                if (getDGNParameters().getXMLFile() != null) {
795
                    File xmlfile = getDGNParameters().getXMLFile();
796
                    try {
797
                        xmlfw = new FileWriter(xmlfile);
798
                        xmlbfw = new BufferedWriter(xmlfw);
799

    
800
                    } catch (Exception ex) {
801
                        xmlfw = null;
802
                        xmlbfw = null;
803
                        logger.warn("Can't open xmfile for output (" + xmlfile.getAbsolutePath() + "'.", ex);
804
                    }
805
                    if (xmlbfw != null) {
806
                        try {
807
                            xmlbfw.write("<DGN>\n");
808
                        } catch (IOException ex) {
809
                            logger.warn("Can't write to the xml file.", ex);
810
                        }
811
                    }
812

    
813
                }
814

    
815
                DGNReader dgnReader = new DGNReader(file.getAbsolutePath(), getDGNParameters().logErrors());
816

    
817
                if ( dgnReader.getInfo().dimension == 2 || getDGNParameters().ignoreZs() ) {
818
                    envelope = geomManager.createEnvelope(SUBTYPES.GEOM2D);
819
                } else {
820
                    envelope = geomManager.createEnvelope(SUBTYPES.GEOM3D);
821
                }
822
                
823
                FeatureType type = getDefaultType().getNotEditableCopy();
824

    
825
                filter = new Filter(getDGNParameters(), dgnReader);
826

    
827
                int counterOfElement = 0;
828
                DGNElemComplexHeader parentElement = null;
829
                
830
                double zvalue = 0;
831
                
832
                for (int id = 0; id < dgnReader.getNumEntities(); id++) {
833
                    dgnReader.DGNGotoElement(id);
834

    
835
                    DGNElemCore elemento = dgnReader.DGNReadElement();
836
                    if (elemento == null) {
837
                        continue;
838
                    }
839

    
840
                    if (parentElement != null) {
841
                        counterOfElement++;
842
                        if (parentElement.getNumElements() < counterOfElement) {
843
                            // Ya hemos terminado de recorrer el elemento complejo.
844
                            parentElement = null;
845
                        }
846
                    }
847

    
848
                    if (xmlbfw != null) {
849
                        // Volcamos el elemnto del DGN a fichero en formato XML
850
                        try {
851
                            xmlbfw.write(dgnReader.DGNDumpElement(dgnReader.getInfo(), elemento));
852
                        } catch (IOException ex) {
853
                            logger.warn("Can't write to the xml file.", ex);
854
                        }
855
                    }
856

    
857
                    if (elemento.isDeleted()) {
858
//                      Saltamos los elementos borrados.
859
                        continue;
860
                    }
861

    
862
                    FeatureProvider data = createFeatureProvider(type);
863

    
864
                    data.set(ID_FIELD_ID, elemento.getID());
865
                    data.set(ID_FIELD_TYPE, elemento.getType());
866
                    data.set(ID_FIELD_STYPE, elemento.getSType());
867
                    data.set(ID_FIELD_LEVEL, elemento.getLevelAsString());
868
                    data.set(ID_FIELD_COLOR, elemento.getColor());
869
                    data.set(ID_FIELD_FILLCOLOR, elemento.getShapeFillColor());
870
                    data.set(ID_FIELD_ENTITY, elemento.getEntityName());
871
                    data.set(ID_FIELD_STYLE, elemento.getStyle());
872
                    data.set(ID_FIELD_WEIGHT, elemento.getWeight());
873
                    data.set(ID_FIELD_GROUP, elemento.getGroup());
874
                    data.set(ID_FIELD_ELEVATION, elemento.getElevation());
875
                    data.set(ID_FIELD_ISCOMPLEXSHAPEHEADER, elemento.isComplexShapeHeader());
876
                    data.set(ID_FIELD_ISSHAPE, elemento.isShape());
877
                    data.set(ID_FIELD_ISHOLE, elemento.isHole());
878
                    data.set(ID_FIELD_ISCOMPLEX, elemento.isComplex());
879
                    data.set(ID_FIELD_HEIGHTTEXT, 0);
880
                    data.set(ID_FIELD_HEIGHTTEXTRAW, 0);
881
                    data.set(ID_FIELD_ROTATIONTEXT, 0);
882
                    data.set(ID_FIELD_TEXT, null);
883
                    data.set(ID_FIELD_SCALE, dgnReader.getInfo().scale);
884
                    if (parentElement == null) {
885
                        data.set(ID_FIELD_PARENT, elemento.getID());
886
                    } else {
887
                        data.set(ID_FIELD_PARENT, parentElement.getID());
888
                    }
889
                    zvalue = 0;
890
                    try {
891
                        switch (elemento.stype) {
892
                            case DGNFileHeader.DGNST_COMPLEX_HEADER:
893
                                parentElement = (DGNElemComplexHeader) elemento;
894
                                counterOfElement = 0;
895
                                break;
896

    
897
                            case DGNFileHeader.DGNST_MULTIPOINT:
898
                                DGNElemMultiPoint dgnmultipoint = (DGNElemMultiPoint) elemento;
899
                                if (dgnmultipoint.isPoint()) {
900
                                    DGNPoint p = dgnmultipoint.getPoint(0);
901
                                    Point point = createPoint3D(p.getX(), p.getY(), ignoreZs ? 0 : p.getZ());
902
                                    data.setDefaultGeometry(point);
903
                                    zvalue = p.getZ();
904
                                } else {
905
                                    OrientablePrimitive geom = null;
906
                                    if (dgnmultipoint.isPolygon()) {
907
                                        geom = geomManager.createSurface(
908
                                                dgnmultipoint.is3D()
909
                                                ? Geometry.SUBTYPES.GEOM3D
910
                                                : Geometry.SUBTYPES.GEOM2D
911
                                        );
912
                                    } else {
913
                                        geom = geomManager.createCurve(
914
                                                dgnmultipoint.is3D()
915
                                                ? Geometry.SUBTYPES.GEOM3D
916
                                                : Geometry.SUBTYPES.GEOM2D
917
                                        );
918
                                    }
919

    
920
                                    // Si es una curva nos saltamos los dos primeros y los dos ultimos vertices.
921
                                    int first = 0;
922
                                    int numVertices = dgnmultipoint.getNumVertices();
923
                                    if (dgnmultipoint.isCurve()) {
924
                                        first = 2;
925
                                        numVertices = dgnmultipoint.getNumVertices() - 2;
926
                                    }
927

    
928
                                    if (dgnmultipoint.isHole()) {
929
                                        // Invertimos el orden porque es un agujero
930
                                        for (int i = numVertices - 2; i >= first; i--) {
931
                                            DGNPoint p = dgnmultipoint.getVertex(i);
932
                                            zvalue = p.getZ();
933
                                            geom.addVertex(p.getX(), p.getY(), ignoreZs ? 0 : zvalue);
934
                                        }
935
                                    } else {
936
                                        for (int i = first; i < numVertices; i++) {
937
                                            DGNPoint p = dgnmultipoint.getVertex(i);
938
                                            zvalue = p.getZ();
939
                                            geom.addVertex(p.getX(), p.getY(), ignoreZs ? 0 : zvalue);
940
                                        }
941
                                    }
942
                                    data.setDefaultGeometry(geom);
943
                                }
944
                                break;
945

    
946
                            case DGNFileHeader.DGNST_ARC:
947
                                DGNElemArc dgnarc = (DGNElemArc) elemento;
948

    
949
                                // La definici?n de arco de MicroStation es distinta a
950
                                // la de Java.
951
                                // En el dgn el origin se entiende que es el centro del
952
                                // arco,
953
                                // y a la hora de crear un Arc2D las 2 primeras
954
                                // coordenadas son
955
                                // la esquina inferior izquierda del rect?ngulo que
956
                                // rodea al arco.
957
                                // 1.- Creamos la elipse sin rotaci?n.
958
                                // 2.- Creamos el arco
959
                                // 3.- Rotamos el resultado
960
                                AffineTransform mT = AffineTransform.getRotateInstance(
961
                                        Math.toRadians(dgnarc.rotation), dgnarc.origin.x,
962
                                        dgnarc.origin.y);
963

    
964
                                // mT.preConcatenate(AffineTransform.getScaleInstance(100.0,100.0));
965
                                Arc2D.Double elArco = new Arc2D.Double(
966
                                        dgnarc.origin.x - dgnarc.primary_axis,
967
                                        dgnarc.origin.y - dgnarc.secondary_axis,
968
                                        2.0 * dgnarc.primary_axis,
969
                                        2.0 * dgnarc.secondary_axis,
970
                                        -dgnarc.startang,
971
                                        -dgnarc.sweepang,
972
                                        Arc2D.OPEN);
973

    
974
                                zvalue = dgnarc.origin.getZ();
975
                                
976
                                GeneralPathX elShapeArc = new GeneralPathX(elArco.getPathIterator(null));
977

    
978
                                // Transformamos el GeneralPahtX porque si transformamos
979
                                // elArco nos lo convierte
980
                                // a GeneralPath y nos guarda las coordenadas en float,
981
                                // con la correspondiente p?rdida de precisi?n
982
                                elShapeArc.transform(mT);
983

    
984
                                Geometry geom = null;
985
                                if (dgnarc.isSurface()) {
986
                                    geom = geomManager.createSurface(elShapeArc,
987
                                            dgnarc.is3D()
988
                                            ? Geometry.SUBTYPES.GEOM3D
989
                                            : Geometry.SUBTYPES.GEOM2D
990
                                    );
991
                                } else {
992
                                    geom = geomManager.createCurve(elShapeArc,
993
                                            dgnarc.is3D()
994
                                            ? Geometry.SUBTYPES.GEOM3D
995
                                            : Geometry.SUBTYPES.GEOM2D
996
                                    );
997
                                }
998
                                data.setDefaultGeometry(geom);
999
                                break;
1000

    
1001
                            case DGNFileHeader.DGNST_TEXT:
1002
                                DGNElemText dgntext = (DGNElemText) elemento;
1003
                                zvalue = dgntext.getPoint().getZ();
1004
                                Point point = createPoint3D(
1005
                                        dgntext.getPoint().getX(),
1006
                                        dgntext.getPoint().getY(),
1007
                                        ignoreZs ? 0 : zvalue
1008
                                );
1009
                                data.set(ID_FIELD_HEIGHTTEXT, dgntext.getHeight());
1010
                                data.set(ID_FIELD_HEIGHTTEXTRAW, dgntext.getRawHeight());
1011
                                data.set(ID_FIELD_ROTATIONTEXT, dgntext.getRotation());
1012
                                data.set(ID_FIELD_TEXT, dgntext.getText());
1013

    
1014
                                data.setDefaultGeometry(point);
1015
                                break;
1016

    
1017
                            default:
1018
                                break;
1019

    
1020
                        } // switch
1021
                    } catch (Exception ex) {
1022
                        logger.warn("Can't process element", ex);
1023
                    }
1024
                    if( useZAsElevation ) {
1025
                        if( !DGNStoreProvider.equals(elevationFactor, 1, 0.00001) ) {
1026
                            zvalue = zvalue*elevationFactor;
1027
                        }
1028
                        if( applyRoundToElevation ) {
1029
                            zvalue = Math.round(zvalue);
1030
                        }
1031
                        data.set(ID_FIELD_ELEVATION, zvalue);
1032
                    }
1033
                    addFeature(data, dgnReader);
1034
                } // for
1035

    
1036
                if (xmlbfw != null) {
1037
                    try {
1038
                        xmlbfw.write("</DGN>\n");
1039
                    } catch (IOException ex) {
1040
                        logger.warn("Can't write to the xml file.", ex);
1041
                    }
1042
                }
1043

    
1044
                consolideGroups(dgnReader);
1045
                if (getDGNParameters().sortByGeometryType()) {
1046
                    sortRows();
1047
                }
1048

    
1049
            } catch (Exception ex) {
1050
                logger.warn("Can't process DGN file", ex);
1051
            } finally {
1052
                IOUtils.closeQuietly(xmlbfw);
1053
                IOUtils.closeQuietly(xmlfw);
1054
            }
1055

    
1056
        }
1057

    
1058
        private void consolideGroups(DGNReader dgnReader) {
1059
            if (groupedFeatures == null) {
1060
                return;
1061
            }
1062
            boolean applyConvexHull = getDGNParameters().getApplyConvexHull();
1063
            FilteredLogger log = new FilteredLogger(logger, "ConsolideGroupBy", 10);
1064

    
1065
            Iterator<Map.Entry<Object, FeatureProvider>> it = groupedFeatures.entrySet().iterator();
1066
            while (it.hasNext()) {
1067
                Map.Entry<Object, FeatureProvider> entry = it.next();
1068
                String groupValue = "<null>";
1069
                if (entry.getKey() != null) {
1070
                    groupValue = entry.getKey().toString();
1071
                }
1072
                try {
1073
                    FeatureProvider data = entry.getValue();
1074
                    Geometry geometry = data.getDefaultGeometry();
1075
                    if (geometry != null) {
1076
                        if (applyConvexHull) {
1077
                            Geometry geom = (Geometry) data.get(ID_FIELD_GEOMETRY);
1078
                            try {
1079
                                data.set(ID_FIELD_GEOMETRY, geom.convexHull());
1080
                            } catch (Exception ex) {
1081
                                log.warn("Can't create convex-hull with geometries of the group '" + groupValue + "'.", ex);
1082
                            }
1083
                        }
1084
                        if (this.envelope == null) {
1085
                            this.envelope = geometry.getEnvelope();
1086
                        } else {
1087
                            this.envelope.add(geometry.getEnvelope());
1088
                        }
1089
                    }
1090
                    addFeatureProvider(data);
1091
                    if (this.leyendBuilder != null) {
1092
                        this.leyendBuilder.process(data, dgnReader);
1093
                    }
1094
                } catch (Exception ex) {
1095
                    log.warn("Problem adding data from group '"+groupValue+"'.", ex);
1096
                }
1097
            }
1098
        }
1099

    
1100
        private void fillRow(Object[] row, DGNElemCore elemento, DGNElemComplexHeader parentElement, DGNReader dgnReader) {
1101
            row[ID_FIELD_HEIGHTTEXT] = new Double(0);
1102
            row[ID_FIELD_HEIGHTTEXTRAW] = new Double(0);
1103
            row[ID_FIELD_ROTATIONTEXT] = new Double(0);
1104
            row[ID_FIELD_TEXT] = null;
1105

    
1106
            row[ID_FIELD_ID] = elemento.getID();
1107
            row[ID_FIELD_TYPE] = elemento.getType();
1108
            row[ID_FIELD_STYPE] = elemento.getSType();
1109
            row[ID_FIELD_LEVEL] = elemento.getLevelAsString();
1110
            row[ID_FIELD_COLOR] = elemento.getColor();
1111
            row[ID_FIELD_FILLCOLOR] = elemento.getShapeFillColor();
1112
            row[ID_FIELD_ENTITY] = elemento.getEntityName();
1113
            row[ID_FIELD_STYLE] = elemento.getStyle();
1114
            row[ID_FIELD_WEIGHT] = elemento.getWeight();
1115
            row[ID_FIELD_GROUP] = elemento.getGroup();
1116
            row[ID_FIELD_ELEVATION] = elemento.getElevation();
1117
            row[ID_FIELD_ISCOMPLEXSHAPEHEADER] = elemento.isComplexShapeHeader();
1118
            row[ID_FIELD_ISSHAPE] = elemento.isShape();
1119
            row[ID_FIELD_ISHOLE] = elemento.isHole();
1120
            row[ID_FIELD_ISCOMPLEX] = elemento.isComplex();
1121
            row[ID_FIELD_PARENT] = elemento.getID();
1122
            if (parentElement != null) {
1123
                row[ID_FIELD_PARENT] = parentElement.getID();
1124
            }
1125
            row[ID_FIELD_SCALE] = dgnReader.getInfo().scale;
1126

    
1127
        }
1128

    
1129
        public void load_group1() throws DataException, CreateEnvelopeException {
1130

    
1131
            this.envelope = null;
1132

    
1133
            FileWriter xmlfw = null;
1134
            BufferedWriter xmlbfw = null;
1135
            if (getDGNParameters().getXMLFile() != null) {
1136
                File xmlfile = getDGNParameters().getXMLFile();
1137
                try {
1138
                    xmlfw = new FileWriter(xmlfile);
1139
                    xmlbfw = new BufferedWriter(xmlfw);
1140

    
1141
                } catch (Exception ex) {
1142
                    xmlfw = null;
1143
                    xmlbfw = null;
1144
                    logger.warn("Can't open xmfile for output (" + xmlfile.getAbsolutePath() + "'.", ex);
1145
                }
1146
                if (xmlbfw != null) {
1147
                    try {
1148
                        xmlbfw.write("<DGN>\n");
1149
                    } catch (IOException ex) {
1150
                        logger.warn("Can't write to the xml file.", ex);
1151
                    }
1152
                }
1153

    
1154
            }
1155
            DGNReader dgnReader = new DGNReader(file.getAbsolutePath());
1156
            if ( dgnReader.getInfo().dimension == 2) {
1157
                envelope = geomManager.createEnvelope(Geometry.SUBTYPES.GEOM2D);
1158
            } else {
1159
                envelope = geomManager.createEnvelope(SUBTYPES.GEOM3D);
1160
            }
1161

    
1162
            FeatureType type = getDefaultType().getNotEditableCopy();
1163
            int fTypeSize = type.size();
1164
            Object[] auxRow = new Object[fTypeSize];
1165
            Object[] cellRow = new Object[fTypeSize];
1166
            Object[] complexRow = new Object[fTypeSize];
1167

    
1168
            boolean bElementoCompuesto = false;
1169
            boolean bEsPoligono = false;
1170
            boolean bInsideCell = false;
1171
            boolean bFirstHoleEntity = false;
1172
            boolean bConnect = false; // Se usa para que los pol?gonos cierren
1173
            // bien cuando son formas compuestas
1174
//                        int contadorSubElementos = 0;
1175
//                        int numSubElementos = 0;
1176
            int complex_index_fill_color = -1;
1177
            int nClass; // Para filtrar los elementos de construcci?n, etc.
1178
            GeneralPathX elementoCompuesto = new GeneralPathX(
1179
                    GeneralPathX.WIND_EVEN_ODD);
1180

    
1181
            int counterOfElement = 0;
1182
            DGNElemComplexHeader parentElement = null;
1183

    
1184
            filter = new Filter(getDGNParameters(), dgnReader);
1185

    
1186
            for (int id = 0; id < dgnReader.getNumEntities(); id++) {
1187
                dgnReader.DGNGotoElement(id);
1188

    
1189
                DGNElemCore elemento = dgnReader.DGNReadElement();
1190
                if (parentElement != null) {
1191
                    counterOfElement++;
1192
                    if (parentElement.getNumElements() < counterOfElement) {
1193
                        // Ya hemos terminado de recorrer el elemento complejo.
1194
                        parentElement = null;
1195
                    }
1196
                }
1197

    
1198
                if (xmlbfw != null && elemento != null) {
1199
                    // Volcamos el elemnto del DGN a fichero en formato XML
1200
                    try {
1201
                        xmlbfw.write(dgnReader.DGNDumpElement(dgnReader.getInfo(), elemento));
1202
                    } catch (IOException ex) {
1203
                        logger.warn("Can't write to the xml file.", ex);
1204
                    }
1205
                }
1206

    
1207
                nClass = 0;
1208
                fillRow(auxRow, elemento, parentElement, dgnReader);
1209
                auxRow[ID_FIELD_HEIGHTTEXT] = new Double(0);
1210
                auxRow[ID_FIELD_ROTATIONTEXT] = new Double(0);
1211
                auxRow[ID_FIELD_TEXT] = null;
1212

    
1213
                if (elemento.properties != 0) {
1214
                    nClass = elemento.properties & DGNFileHeader.DGNPF_CLASS;
1215
                }
1216

    
1217
                if ((elemento != null) && (elemento.deleted == 0)
1218
                        && (nClass == 0)) // Leer un elemento
1219
                {
1220

    
1221
                    // if ((elemento.element_id > 3800) && (elemento.element_id
1222
                    // < 3850))
1223
                    // dgnReader.DGNDumpElement(dgnReader.getInfo(),elemento,"");
1224
                    if ((elemento.stype == DGNFileHeader.DGNST_MULTIPOINT)
1225
                            || (elemento.stype == DGNFileHeader.DGNST_ARC)
1226
                            || (elemento.stype == DGNFileHeader.DGNST_CELL_HEADER)
1227
                            || (elemento.stype == DGNFileHeader.DGNST_SHARED_CELL_DEFN)
1228
                            || (elemento.stype == DGNFileHeader.DGNST_COMPLEX_HEADER)) {
1229
                        if (elemento.complex != 0) {
1230
                            bElementoCompuesto = true;
1231
                        } else {
1232
                            if (bElementoCompuesto) {
1233
                                if (bInsideCell) {
1234
                                    auxRow[ID_FIELD_ENTITY] = cellRow[ID_FIELD_ENTITY];
1235
                                } else {
1236
                                    auxRow = complexRow;
1237
                                }
1238
                                addShape(createMultiCurve(elementoCompuesto),
1239
                                        auxRow, type, dgnReader);
1240

    
1241
                                if (bEsPoligono) {
1242
                                    if (complex_index_fill_color != -1) {
1243
                                        auxRow[ID_FIELD_COLOR] = complex_index_fill_color;
1244
                                    }
1245

    
1246
                                    addShape(
1247
                                            createMultiSurface(elementoCompuesto),
1248
                                            auxRow, type, dgnReader);
1249
                                }
1250

    
1251
                                elementoCompuesto = new GeneralPathX(
1252
                                        GeneralPathX.WIND_EVEN_ODD);
1253
                            }
1254

    
1255
                            bElementoCompuesto = false;
1256
                            bEsPoligono = false;
1257
                            bConnect = false;
1258

    
1259
                            bInsideCell = false;
1260
                        }
1261
                    }
1262

    
1263
                    switch (elemento.stype) {
1264
                        case DGNFileHeader.DGNST_SHARED_CELL_DEFN:
1265
                            bInsideCell = true;
1266
                            fillRow(cellRow, elemento, parentElement, dgnReader);
1267
                            cellRow[ID_FIELD_ID] = elemento.element_id;
1268
                            cellRow[ID_FIELD_LAYER] = String.valueOf(elemento.level);
1269
                            cellRow[ID_FIELD_COLOR] = elemento.color;
1270
                            cellRow[ID_FIELD_ENTITY] = "Shared Cell";
1271

    
1272
                            break;
1273

    
1274
                        case DGNFileHeader.DGNST_CELL_HEADER:
1275
                            bInsideCell = true;
1276

    
1277
                            fillRow(cellRow, elemento, parentElement, dgnReader);
1278
                            cellRow[ID_FIELD_ID] = elemento.element_id;
1279
                            cellRow[ID_FIELD_LAYER] = String.valueOf(elemento.level);
1280
                            cellRow[ID_FIELD_COLOR] = elemento.color;
1281
                            cellRow[ID_FIELD_ENTITY] = "Cell";
1282
                            complex_index_fill_color = dgnReader
1283
                                    .DGNGetShapeFillInfo(elemento);
1284
                            break;
1285

    
1286
                        case DGNFileHeader.DGNST_COMPLEX_HEADER:
1287

    
1288
                            // bElementoCompuesto = true;
1289
//                                                contadorSubElementos = 0;
1290
                            DGNElemComplexHeader psComplexHeader = (DGNElemComplexHeader) elemento;
1291

    
1292
                            parentElement = psComplexHeader;
1293
                            counterOfElement = parentElement.getNumElements();
1294

    
1295
//                                                numSubElementos = psComplexHeader.numelems;
1296
                            fillRow(complexRow, elemento, parentElement, dgnReader);
1297
                            complexRow[ID_FIELD_ID] = elemento.element_id;
1298
                            complexRow[ID_FIELD_LAYER] = String.valueOf(elemento.level);
1299
                            complexRow[ID_FIELD_COLOR] = elemento.color;
1300
                            complexRow[ID_FIELD_ENTITY] = "Complex";
1301

    
1302
                            if (psComplexHeader.type == DGNFileHeader.DGNT_COMPLEX_SHAPE_HEADER) {
1303
                                bEsPoligono = true;
1304

    
1305
                                // Si es un agujero, no conectamos con el anterior
1306
                                if ((psComplexHeader.properties & 0x8000) != 0) {
1307
                                    bFirstHoleEntity = true;
1308
                                } else {
1309
                                    // Miramos si tiene color de relleno
1310
                                    // complex_index_fill_color = -1;
1311
                                    // if (elemento.attr_bytes > 0) {
1312
                                    complex_index_fill_color = dgnReader
1313
                                            .DGNGetShapeFillInfo(elemento);
1314

    
1315
                                    // }
1316
                                }
1317

    
1318
                                bConnect = true;
1319
                            } else {
1320
                                bEsPoligono = false;
1321
                                bConnect = false;
1322
                            }
1323

    
1324
                            break;
1325

    
1326
                        case DGNFileHeader.DGNST_MULTIPOINT:
1327

    
1328
                            // OJO: Si lo que viene en este multipoint es un
1329
                            // elemento con type=11 (curve), se trata de una
1330
                            // "parametric
1331
                            // spline curve". La vamos a tratar como si no fuera
1332
                            // curva, pero seg?n la documentaci?n, los 2 primeros
1333
                            // puntos
1334
                            // y los 2 ?ltimos puntos definen "endpoint derivatives"
1335
                            // y NO se muestran.
1336
                            // TODAV?A HAY UN PEQUE?O FALLO CON EL FICHERO
1337
                            // dgn-sample.dgn, pero lo dejo por ahora.
1338
                            // Es posible que tenga que ver con lo de los arcos
1339
                            // (arco distorsionado), que
1340
                            // todav?a no est? metido.
1341
                            DGNElemMultiPoint psLine = (DGNElemMultiPoint) elemento;
1342
                            fillRow(auxRow, elemento, parentElement, dgnReader);
1343
                            auxRow[ID_FIELD_ID] = elemento.element_id;
1344
                            auxRow[ID_FIELD_ENTITY] = "Multipoint";
1345
                            auxRow[ID_FIELD_LAYER] = String.valueOf(elemento.level);
1346
                            auxRow[ID_FIELD_COLOR] = elemento.color;
1347

    
1348
                            if ((psLine.num_vertices == 2)
1349
                                    && (psLine.vertices[0].x == psLine.vertices[1].x)
1350
                                    && (psLine.vertices[0].y == psLine.vertices[1].y)) {
1351
                                auxRow[ID_FIELD_ENTITY] = "Point";
1352
                                addShape(
1353
                                        createPoint3D(psLine.vertices[0].x,
1354
                                                psLine.vertices[0].y,
1355
                                                psLine.vertices[0].z), auxRow,
1356
                                        type, dgnReader);
1357
                            } else {
1358
                                GeneralPathX elShape = new GeneralPathX(
1359
                                        GeneralPathX.WIND_EVEN_ODD);
1360

    
1361
                                if (psLine.type == DGNFileHeader.DGNT_CURVE) {
1362
                                    psLine.num_vertices = psLine.num_vertices - 4;
1363

    
1364
                                    for (int aux_n = 0; aux_n < psLine.num_vertices; aux_n++) {
1365
                                        psLine.vertices[aux_n] = psLine.vertices[aux_n + 2];
1366
                                    }
1367
                                }
1368

    
1369
                                if ((psLine.type == DGNFileHeader.DGNT_SHAPE)
1370
                                        && ((psLine.properties & 0x8000) != 0)) {
1371
                                    // Invertimos el orden porque es un agujero
1372
                                    elShape
1373
                                            .moveTo(
1374
                                                    psLine.vertices[psLine.num_vertices - 1].x,
1375
                                                    psLine.vertices[psLine.num_vertices - 1].y);
1376

    
1377
                                    for (int i = psLine.num_vertices - 2; i >= 0; i--) {
1378
                                        elShape.lineTo(psLine.vertices[i].x,
1379
                                                psLine.vertices[i].y);
1380
                                    }
1381
                                } else {
1382
                                    elShape.moveTo(psLine.vertices[0].x,
1383
                                            psLine.vertices[0].y);
1384

    
1385
                                    for (int i = 1; i < psLine.num_vertices; i++) {
1386
                                        elShape.lineTo(psLine.vertices[i].x,
1387
                                                psLine.vertices[i].y);
1388
                                    }
1389
                                }
1390

    
1391
                                if ((psLine.vertices[0].x == psLine.vertices[psLine.num_vertices - 1].x)
1392
                                        && (psLine.vertices[0].y == psLine.vertices[psLine.num_vertices - 1].y)) {
1393
                                    // Lo a?adimos tambi?n como pol?gono
1394
                                    bEsPoligono = true;
1395

    
1396
                                    // Miramos si tiene color de relleno
1397
                                    if (elemento.attr_bytes > 0) {
1398
                                        elemento.color = dgnReader
1399
                                                .DGNGetShapeFillInfo(elemento);
1400

    
1401
                                        if (elemento.color != -1) {
1402
                                            auxRow[ID_FIELD_COLOR] = elemento.color;
1403
                                        }
1404
                                    }
1405

    
1406
                                    if (elemento.complex == 0) {
1407
                                        addShape(createSurface(elShape), auxRow,
1408
                                                type, dgnReader);
1409
                                    }
1410
                                }
1411

    
1412
                                if (elemento.complex != 0) {
1413
                                    // Si es un agujero o
1414
                                    // es la primera entidad del agujero, lo
1415
                                    // a?adimos sin unir al anterior
1416
                                    if (bFirstHoleEntity
1417
                                            || ((psLine.type == DGNFileHeader.DGNT_SHAPE) && ((psLine.properties & 0x8000) != 0))) {
1418
                                        elementoCompuesto.append(elShape.getPathIterator(null), false);
1419
                                        bFirstHoleEntity = false;
1420
                                    } else {
1421
                                        elementoCompuesto.append(elShape.getPathIterator(null), bConnect);
1422
                                    }
1423
                                } else {
1424
                                    addShape(createMultiCurve(elShape), auxRow,
1425
                                            type, dgnReader);
1426
                                }
1427
                            }
1428

    
1429
                            break;
1430

    
1431
                        case DGNFileHeader.DGNST_ARC:
1432

    
1433
                            // dgnReader.DGNDumpElement(dgnReader.getInfo(),
1434
                            // elemento,"");
1435
                            DGNElemArc psArc = (DGNElemArc) elemento;
1436

    
1437
                            // La definici?n de arco de MicroStation es distinta a
1438
                            // la de Java.
1439
                            // En el dgn el origin se entiende que es el centro del
1440
                            // arco,
1441
                            // y a la hora de crear un Arc2D las 2 primeras
1442
                            // coordenadas son
1443
                            // la esquina inferior izquierda del rect?ngulo que
1444
                            // rodea al arco.
1445
                            // 1.- Creamos la elipse sin rotaci?n.
1446
                            // 2.- Creamos el arco
1447
                            // 3.- Rotamos el resultado
1448
                            AffineTransform mT = AffineTransform.getRotateInstance(
1449
                                    Math.toRadians(psArc.rotation), psArc.origin.x,
1450
                                    psArc.origin.y);
1451

    
1452
                            // mT.preConcatenate(AffineTransform.getScaleInstance(100.0,100.0));
1453
                            Arc2D.Double elArco = new Arc2D.Double(psArc.origin.x
1454
                                    - psArc.primary_axis, psArc.origin.y
1455
                                    - psArc.secondary_axis,
1456
                                    2.0 * psArc.primary_axis,
1457
                                    2.0 * psArc.secondary_axis, -psArc.startang,
1458
                                    -psArc.sweepang, Arc2D.OPEN);
1459

    
1460
                            // Ellipse2D.Double elArco = new
1461
                            // Ellipse2D.Double(psArc.origin.x - psArc.primary_axis,
1462
                            // psArc.origin.y - psArc.secondary_axis,2.0 *
1463
                            // psArc.primary_axis, 2.0 * psArc.secondary_axis);
1464
                            GeneralPathX elShapeArc = new GeneralPathX(elArco.getPathIterator(null));
1465

    
1466
                            // Transformamos el GeneralPahtX porque si transformamos
1467
                            // elArco nos lo convierte
1468
                            // a GeneralPath y nos guarda las coordenadas en float,
1469
                            // con la correspondiente p?rdida de precisi?n
1470
                            elShapeArc.transform(mT);
1471

    
1472
                            if (dgnReader.getInfo().dimension == 3) {
1473
                                // Aqu? podr?amos hacer cosas con la coordenada Z
1474
                            }
1475

    
1476
                            fillRow(auxRow, elemento, parentElement, dgnReader);
1477
                            auxRow[ID_FIELD_ID] = elemento.element_id;
1478
                            auxRow[ID_FIELD_ENTITY] = "Arc";
1479
                            auxRow[ID_FIELD_LAYER] = String.valueOf(elemento.level);
1480
                            auxRow[ID_FIELD_COLOR] = elemento.color;
1481

    
1482
                            /*
1483
                             * Line2D.Double ejeMayor = new
1484
                             * Line2D.Double(psArc.origin.x - psArc.primary_axis,
1485
                             * psArc.origin.y, psArc.origin.x + psArc.primary_axis,
1486
                             * psArc.origin.y);
1487
                             *
1488
                             * lyrLines.addShape(new
1489
                             * FShape(FConstant.SHAPE_TYPE_POLYLINE, new
1490
                             * GeneralPathX(ejeMayor)), auxRow);
1491
                             */
1492
                            // lyrLines.addShape(new
1493
                            // FShape(FConstant.SHAPE_TYPE_POLYLINE, elShapeArc),
1494
                            // auxRow);
1495
                            if (elemento.complex != 0) {
1496
                                // Esto es una posible fuente de fallos si detr?s de
1497
                                // una
1498
                                // elipse vienen m?s cosas pegadas. Deber?amos
1499
                                // volver
1500
                                // a conectar una vez pasada la elipse.
1501
                                if (elemento.type == DGNFileHeader.DGNT_ELLIPSE) {
1502
                                    bConnect = false;
1503
                                }
1504

    
1505
                                // SI LA ELIPSE ES UN AGUJERO, SE A?ADE SIN PEGAR
1506
                                // Y EL ELEMENTO ES UN POLIGONO
1507
                                if (bFirstHoleEntity
1508
                                        || ((elemento.type == DGNFileHeader.DGNT_SHAPE) && ((elemento.properties & 0x8000) != 0))) {
1509
                                    elementoCompuesto.append(elShapeArc.getPathIterator(null), false);
1510
                                    bFirstHoleEntity = false;
1511
                                } else {
1512
                                    elementoCompuesto.append(elShapeArc.getPathIterator(null), bConnect);
1513
                                }
1514
                            } else {
1515
                                addShape(createMultiCurve(elShapeArc), auxRow,
1516
                                        type, dgnReader);
1517

    
1518
                                if (psArc.type == DGNFileHeader.DGNT_ELLIPSE) {
1519
                                    addShape(createSurface(elShapeArc), auxRow,
1520
                                            type, dgnReader);
1521
                                }
1522
                            }
1523

    
1524
                            break;
1525

    
1526
                        case DGNFileHeader.DGNST_TEXT:
1527

    
1528
                            DGNElemText psText = (DGNElemText) elemento;
1529
                            Geometry elShapeTxt = createPoint3D(psText.origin.x,
1530
                                    psText.origin.y, psText.origin.z);
1531

    
1532
                            fillRow(auxRow, elemento, parentElement, dgnReader);
1533
                            auxRow[ID_FIELD_ID] = elemento.element_id;
1534
                            auxRow[ID_FIELD_ENTITY] = "Text";
1535
                            auxRow[ID_FIELD_LAYER] = String.valueOf(elemento.level);
1536
                            auxRow[ID_FIELD_COLOR] = elemento.color;
1537
                            auxRow[ID_FIELD_HEIGHTTEXT] = psText.height_mult;
1538
                            auxRow[ID_FIELD_HEIGHTTEXTRAW] = psText.height_raw;
1539
                            auxRow[ID_FIELD_ROTATIONTEXT] = psText.rotation;
1540
                            auxRow[ID_FIELD_TEXT] = psText.string; // .trim();
1541
                            addShape(elShapeTxt, auxRow, type, dgnReader);
1542
                            break;
1543

    
1544
                        /*
1545
                         * default:
1546
                         * dgnReader.DGNDumpElement(dgnReader.getInfo(),
1547
                         * elemento, "");
1548
                         */
1549
                    } // switch
1550
                } // if
1551
            } // for
1552

    
1553
            if (bElementoCompuesto) {
1554
                if (bInsideCell) {
1555
                    auxRow = cellRow;
1556
                } else {
1557
                    auxRow = complexRow;
1558
                }
1559

    
1560
                addShape(createMultiCurve(elementoCompuesto), auxRow, type,
1561
                        dgnReader);
1562

    
1563
                if (bEsPoligono) {
1564
                    if (complex_index_fill_color != -1) {
1565
                        auxRow[ID_FIELD_COLOR] = complex_index_fill_color;
1566
                    }
1567

    
1568
                    addShape(createSurface(elementoCompuesto), auxRow, type,
1569
                            dgnReader);
1570
                }
1571
            }
1572

    
1573
            if (xmlbfw != null) {
1574
                try {
1575
                    xmlbfw.write("</DGN>\n");
1576
                } catch (IOException ex) {
1577
                    logger.warn("Can't write to the xml file.", ex);
1578
                }
1579
                IOUtils.closeQuietly(xmlbfw);
1580
                IOUtils.closeQuietly(xmlfw);
1581
            }
1582

    
1583
        }
1584

    
1585
        private Geometry createMultiSurface(GeneralPathX elementoCompuesto)
1586
                throws DataException {
1587
            try {
1588
                return geomManager.createMultiSurface(elementoCompuesto,
1589
                        SUBTYPES.GEOM2D);
1590
            } catch (CreateGeometryException e) {
1591
                throw new org.gvsig.fmap.dal.feature.exception.CreateGeometryException(
1592
                        e);
1593
            }
1594

    
1595
        }
1596

    
1597
        private Curve createCurve(boolean is3D) throws CreateGeometryException {
1598
            if (is3D) {
1599
                return (Curve) geomManager.create(
1600
                        Geometry.TYPES.CURVE,
1601
                        Geometry.SUBTYPES.GEOM3D);
1602
            }
1603
            return (Curve) geomManager.create(
1604
                    Geometry.TYPES.CURVE,
1605
                    Geometry.SUBTYPES.GEOM2D);
1606

    
1607
        }
1608

    
1609
        private Point createPoint3D(double x, double y, double z)
1610
                throws DataException {
1611
            Point point;
1612
            try {
1613
                // point = (Point) geomManager.create(TYPES.POINT,
1614
                // SUBTYPES.GEOM3D);
1615
                point = (Point) geomManager.create(TYPES.POINT,
1616
                        SUBTYPES.GEOM3D);
1617
            } catch (CreateGeometryException e) {
1618
                throw new org.gvsig.fmap.dal.feature.exception.CreateGeometryException(
1619
                        e);
1620
            }
1621
            point.setCoordinates(new double[]{x, y, z});
1622

    
1623
            return point;
1624
        }
1625

    
1626
        private int getGroupByFieldIndex() {
1627
            if (groupByFieldIndex > -2) {
1628
                return groupByFieldIndex;
1629
            }
1630
            String groupby = getDGNParameters().getGroupBy();
1631
            if (groupby == null) {
1632
                groupByFieldIndex = -1;
1633
                return groupByFieldIndex;
1634
            }
1635
            groupByFieldIndex = this.getDefaultType().getIndex(groupby);
1636
            return groupByFieldIndex;
1637
        }
1638

    
1639
        private MultiPrimitive getMultiPrimitive(Geometry geom) {
1640
            if (geom == null) {
1641
                return null;
1642
            }
1643
            if (geom instanceof MultiPrimitive) {
1644
                return (MultiPrimitive) geom;
1645
            }
1646
            MultiPrimitive multi = null;
1647
            try {
1648
                if (geom instanceof Point) {
1649
                    multi = (MultiPrimitive) geomManager.create(
1650
                            TYPES.MULTIPOINT,
1651
                            geom.getGeometryType().getSubType()
1652
                    );
1653
                } else if (geom instanceof Curve) {
1654
                    multi = (MultiPrimitive) geomManager.create(
1655
                            TYPES.MULTICURVE,
1656
                            geom.getGeometryType().getSubType()
1657
                    );
1658
                } else if (geom instanceof Surface) {
1659
                    multi = (MultiPrimitive) geomManager.create(
1660
                            TYPES.MULTISURFACE,
1661
                            geom.getGeometryType().getSubType()
1662
                    );
1663
                }
1664
                if (multi != null) {
1665
                    multi.addPrimitive((Primitive) geom);
1666
                }
1667
            } catch (CreateGeometryException ex) {
1668
                logger.warn("Can't create multi-geometry to group", ex);
1669
            }
1670
            return multi;
1671
        }
1672

    
1673
        private void addToGroup(int groupbyField, FeatureProvider data) {
1674
            if (groupedFeatures == null) {
1675
                groupedFeatures = new HashMap<Object, FeatureProvider>();
1676
            }
1677
            Object groupbyValue = data.get(groupbyField);
1678
            FeatureProvider group = groupedFeatures.get(groupbyValue);
1679
            if (group == null) {
1680
                groupedFeatures.put(groupbyValue, data);
1681
                MultiPrimitive multi = getMultiPrimitive((Geometry) data.get(ID_FIELD_GEOMETRY));
1682
                if (multi == null) {
1683
                    data.set(ID_FIELD_GEOMETRY, null);
1684
                } else {
1685
                    data.set(ID_FIELD_GEOMETRY, multi);
1686
                }
1687
                return;
1688
            }
1689
            for (int i = 0; i <= MAX_FIELD_ID; i++) {
1690
                Object value = group.get(i);
1691
                if (i == ID_FIELD_GEOMETRY) {
1692
                    Geometry newgeom = (Geometry) data.get(i);
1693
                    if (newgeom != null) {
1694
                        if (value == null) {
1695
                            group.set(ID_FIELD_GEOMETRY, getMultiPrimitive(newgeom));
1696
                        } else {
1697
                            try {
1698
                                ((MultiPrimitive) value).addPrimitive((Primitive) newgeom);
1699
                            } catch (Exception ex) {
1700
                                logger.warn("Can't group geoemtry '" + newgeom.toString() + "' in '" + value.toString() + "'.", ex);
1701
                            }
1702
                        }
1703
                    }
1704
                } else if (value == null) {
1705
                    group.set(i, data.get(i));
1706
                } else if (value instanceof String) {
1707
                    String s = (String) value;
1708
                    if (s.trim().length() == 0) {
1709
                        group.set(i, data.get(i));
1710
                    }
1711
                }
1712
            }
1713

    
1714
        }
1715

    
1716
        private void addFeature(FeatureProvider data, DGNReader dgnReader) throws DataException {
1717

    
1718
            if (!filter.accept(data)) {
1719
                return;
1720
            }
1721
            int groupByIndex = this.getGroupByFieldIndex();
1722
            if (groupByIndex >= 0) {
1723
                addToGroup(groupByIndex, data);
1724
                return;
1725
            }
1726
            addFeatureProvider(data);
1727
            Geometry geometry = data.getDefaultGeometry();
1728
            if (geometry != null) {
1729
                if (this.envelope == null) {
1730
                    this.envelope = geometry.getEnvelope();
1731
                } else {
1732
                    this.envelope.add(geometry.getEnvelope());
1733
                }
1734
            }
1735
            if (this.leyendBuilder != null) {
1736
                this.leyendBuilder.process(data, dgnReader);
1737
            }
1738
        }
1739

    
1740
        private void addShape(Geometry geometry, Object[] auxRow,
1741
                FeatureType type, DGNReader dgnReader) throws DataException {
1742

    
1743
            FeatureProvider data = createFeatureProvider(type);
1744
            for (int i = 0; i < type.size(); i++) {
1745
                data.set(i, auxRow[i]);
1746
            }
1747
            data.setDefaultGeometry(geometry);
1748
            addFeature(data, dgnReader);
1749
        }
1750

    
1751
        private Geometry createMultiCurve(GeneralPathX elementoCompuesto)
1752
                throws DataException {
1753
            try {
1754
                return geomManager.createMultiCurve(elementoCompuesto,
1755
                        SUBTYPES.GEOM2D);
1756
            } catch (CreateGeometryException e) {
1757
                throw new org.gvsig.fmap.dal.feature.exception.CreateGeometryException(
1758
                        e);
1759
            }
1760
        }
1761

    
1762
        private Geometry createSurface(GeneralPathX elementoCompuesto)
1763
                throws DataException {
1764
            try {
1765
                return geomManager.createCurve(elementoCompuesto,
1766
                        SUBTYPES.GEOM2D);
1767
            } catch (CreateGeometryException e) {
1768
                throw new org.gvsig.fmap.dal.feature.exception.CreateGeometryException(
1769
                        e);
1770
            }
1771

    
1772
        }
1773

    
1774
    }
1775

    
1776
    public boolean closeResourceRequested(ResourceProvider resource) {
1777
        return true;
1778
    }
1779

    
1780
    public int getOIDType() {
1781
        return DataTypes.LONG;
1782
    }
1783

    
1784
    public boolean supportsAppendMode() {
1785
        return false;
1786
    }
1787

    
1788
    public void append(FeatureProvider featureProvider) {
1789
        throw new UnsupportedOperationException();
1790
    }
1791

    
1792
    public void beginAppend() {
1793
        throw new UnsupportedOperationException();
1794
    }
1795

    
1796
    public void endAppend() {
1797
        throw new UnsupportedOperationException();
1798
    }
1799

    
1800
    public Object createNewOID() {
1801
        return new Long(counterNewsOIDs++);
1802
    }
1803

    
1804
    protected void initializeFeatureTypes() throws InitializeException {
1805
        try {
1806
            this.open();
1807
        } catch (OpenException e) {
1808
            throw new InitializeException(this.getProviderName(), e);
1809
        }
1810
    }
1811

    
1812
    public Envelope getEnvelope() throws DataException {
1813
        this.open();
1814
        return (Envelope) this.getDynValue("Envelope");
1815
    }
1816

    
1817

    
1818
    /*
1819
     * (non-Javadoc)
1820
     *
1821
     * @see
1822
     * org.gvsig.fmap.dal.resource.spi.ResourceConsumer#resourceChanged(org.
1823
     * gvsig.fmap.dal.resource.spi.ResourceProvider)
1824
     */
1825
    public void resourceChanged(ResourceProvider resource) {
1826
        this.getStoreServices().notifyChange(
1827
                DataStoreNotification.RESOURCE_CHANGED,
1828
                resource);
1829
    }
1830

    
1831
    public Object getSourceId() {
1832
        return this.getDGNParameters().getFile();
1833
    }
1834

    
1835
    public String getName() {
1836
        String name = this.getDGNParameters().getFile().getName();
1837
        int n = name.lastIndexOf(".");
1838
        if (n < 1) {
1839
            return name;
1840
        }
1841
        return name.substring(0, n);
1842
    }
1843

    
1844
    public String getFullName() {
1845
        return this.getDGNParameters().getFile().getAbsolutePath();
1846
    }
1847

    
1848
    public ResourceProvider getResource() {
1849
        return resource;
1850
    }
1851

    
1852
    public static boolean equals(double a, double b, double precision) {
1853
        double v = Math.abs(a-b);
1854
        return v < precision;
1855
    }
1856
}