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 @ 75

History | View | Annotate | Download (80.5 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 boolean isActiveOption(String option) {
252
        if (option == null) {
253
            return false;
254
        }
255
        String options = getDGNParameters().getDebugOptions();
256
        if (options == null) {
257
            return false;
258
        }
259
        option = " " + option.toLowerCase() + " ";
260
        options = "  " + options.toLowerCase() + " ";
261
        return options.contains(option);
262
    }
263

    
264
    public void open() throws OpenException {
265
        if (this.data != null) {
266
            return;
267
        }
268
        try {
269
            getResource().execute(new ResourceAction() {
270
                public Object run() throws Exception {
271
                    FeatureStoreProviderServices store = getStoreServices();
272
                    if (dgndata == null
273
                            && !(getDGNParameters().useReload() || isActiveOption("reload"))) {
274
                        if (resource.getData() != null) {
275
                            dgndata = (DGNData) ((Map) resource.getData()).get(projection.getAbrev()); // OJO
276
                            // no es del todo correcto (puede llevar reproyeccion)
277
                        } else {
278
                            resource.setData(new HashMap());
279
                        }
280
                    }
281

    
282
                    if (dgndata == null) {
283
                        dgndata = new DGNData();
284
                        dgndata.data = new ArrayList();
285
                        data = dgndata.data;
286
                        counterNewsOIDs = 0;
287
                        Reader reader = new Reader().initialice(
288
                                getMemoryProvider(),
289
                                (File) resource.get(),
290
                                projection, legendBuilder);
291
                        reader.begin(store);
292
                        dgndata.defaultFType = reader.getDefaultType().getNotEditableCopy();
293
                        List types = new ArrayList();
294
                        Iterator it = reader.getTypes().iterator();
295
                        EditableFeatureType fType;
296
                        while (it.hasNext()) {
297
                            fType = (EditableFeatureType) it.next();
298
                            if (fType.getId().equals(
299
                                    dgndata.defaultFType.getId())) {
300
                                types.add(dgndata.defaultFType);
301
                            } else {
302
                                types.add(fType.getNotEditableCopy());
303
                            }
304
                        }
305
                        dgndata.fTypes = types;
306

    
307
                        resource.notifyOpen();
308
                        store.setFeatureTypes(dgndata.fTypes,
309
                                dgndata.defaultFType);
310
                        reader.load();
311
                        dgndata.envelope = reader.getEnvelope();
312
                        dgndata.legendBuilder = legendBuilder;
313
                        dgndata.projection = projection;
314
                        reader.end();
315
                        if (resource.getData() == null) {
316
                            resource.setData(new HashMap());
317
                        }
318
                        ((Map) resource.getData()).put(
319
                                projection.getAbrev(),
320
                                dgndata); // OJO la reproyeccion
321
                        resource.notifyClose();
322
                    }
323

    
324
                    data = dgndata.data;
325
                    store.setFeatureTypes(dgndata.fTypes, dgndata.defaultFType);
326
                    legendBuilder = dgndata.legendBuilder;
327
                    setDynValue("Envelope", dgndata.getEnvelopeCopy());
328
                    setDynValue("CRS", projection);
329
                    counterNewsOIDs = data.size();
330
                    return null;
331
                }
332
            });
333
        } catch (Exception e) {
334
            data = null;
335
            try {
336
                throw new OpenException(resource.getName(), e);
337
            } catch (AccessResourceException e1) {
338
                throw new OpenException(getProviderName(), e);
339
            }
340
        }
341
    }
342

    
343
    private void sortRows() {
344
        List rows = this.data;
345

    
346
        Collections.sort(rows, new Comparator<FeatureProvider>() {
347
            public int compare(FeatureProvider o1, FeatureProvider o2) {
348
                Geometry g1 = o1.getDefaultGeometry();
349
                Geometry g2 = o2.getDefaultGeometry();
350
                if (g1 == null) {
351
                    if (g2 == null) {
352
                        return 0;
353
                    } else {
354
                        return -1;
355
                    }
356
                } else if (g2 == null) {
357
                    return 1;
358
                }
359
                return g2.getType() - g1.getType();
360
            }
361
        });
362
    }
363

    
364
    public DataServerExplorer getExplorer() throws ReadException {
365
        DataManager manager = DALLocator.getDataManager();
366
        FilesystemServerExplorerParameters params;
367
        try {
368
            params = (FilesystemServerExplorerParameters) manager
369
                    .createServerExplorerParameters(FilesystemServerExplorer.NAME);
370
            params.setRoot(this.getDGNParameters().getFile().getParent());
371
            return manager.openServerExplorer(FilesystemServerExplorer.NAME, params);
372
        } catch (DataException e) {
373
            throw new ReadException(this.getProviderName(), e);
374
        } catch (ValidateDataParametersException e) {
375
            throw new ReadException(this.getProviderName(), e);
376
        }
377

    
378
    }
379

    
380
    public void performChanges(Iterator deleteds, Iterator inserteds, Iterator updateds, Iterator originalFeatureTypesUpdated) throws PerformEditingException {
381
        // FIXME Exception
382
        throw new UnsupportedOperationException();
383
    }
384

    
385
    public class Filter {
386

    
387
        private Pattern levelFilter = null;
388
        private Pattern colorFilter = null;
389
        private Pattern styleFilter = null;
390
        private Pattern weighFilter = null;
391
        private Pattern typeFilter = null;
392
        private Pattern stypeFilter = null;
393
        private Pattern idFilter = null;
394
        private Pattern groupFilter = null;
395
        private Pattern textFilter = null;
396
        private Point pointForCheckGeometries = null;
397
        private boolean hasfilter = false;
398
        private boolean skipCurruptGeometries = true;
399
        private int geometryTypeFilter = Geometry.TYPES.GEOMETRY;
400
        private int counter_exceptions = 0;
401
        private int cropOperationFilter;
402
        private Geometry cropFilter = null;
403

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

    
473
        private boolean match(Pattern exp, Object value) {
474
            if (exp == null) {
475
                return true;
476
            }
477
            if (value == null) {
478
                return false;
479
            }
480
            return exp.matcher(value.toString()).matches();
481
        }
482

    
483
        public boolean accept(FeatureProvider data) {
484

    
485
            if (!this.hasfilter) {
486
                return true;
487
            }
488

    
489
            Geometry geometry = data.getDefaultGeometry();
490
            if (this.pointForCheckGeometries != null) {
491
                if (geometry != null) {
492
                    try {
493
                        this.pointForCheckGeometries.intersects(geometry);
494
                    } catch (Exception ex) {
495
                        // Skip geometries with problems
496
                        data.setDefaultGeometry(null);
497
                        geometry = null;
498
                    }
499
                }
500
            }
501

    
502
            try {
503
                if (!match(levelFilter, data.get(ID_FIELD_LEVEL))) {
504
                    return false;
505
                }
506
                if (!match(colorFilter, data.get(ID_FIELD_COLOR))) {
507
                    return false;
508
                }
509
                if (!match(styleFilter, data.get(ID_FIELD_STYLE))) {
510
                    return false;
511
                }
512
                if (!match(weighFilter, data.get(ID_FIELD_WEIGHT))) {
513
                    return false;
514
                }
515
                if (!match(typeFilter, data.get(ID_FIELD_TYPE))) {
516
                    return false;
517
                }
518
                if (!match(stypeFilter, data.get(ID_FIELD_STYPE))) {
519
                    return false;
520
                }
521
                if (!match(groupFilter, data.get(ID_FIELD_GROUP))) {
522
                    return false;
523
                }
524
                if (!match(idFilter, data.get(ID_FIELD_ID))) {
525
                    return false;
526
                }
527
                if (!match(textFilter, data.get(ID_FIELD_TEXT))) {
528
                    return false;
529
                }
530

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

    
619
    }
620

    
621
    public class Reader {
622

    
623
        private File file;
624
        private IProjection projection;
625
        private List types;
626
        private LegendBuilder leyendBuilder;
627
        private AbstractMemoryStoreProvider store;
628
        private Envelope envelope;
629
        private Filter filter = null;
630

    
631
        public Reader initialice(AbstractMemoryStoreProvider store, File file,
632
                IProjection projection,
633
                LegendBuilder leyendBuilder) {
634
            this.store = store;
635
            this.file = file;
636
            this.projection = projection;
637
            this.leyendBuilder = leyendBuilder;
638
            if (leyendBuilder != null) {
639
                leyendBuilder.initialize(store);
640
            }
641
            return this;
642
        }
643

    
644
        public Envelope getEnvelope() {
645
            return this.envelope;
646
        }
647

    
648
        public void begin(FeatureStoreProviderServices store) {
649

    
650
            EditableFeatureType featureType = store.createFeatureType(getName());
651

    
652
            featureType.setHasOID(true);
653

    
654
            ID_FIELD_ID = featureType.add(NAME_FIELD_ID, DataTypes.INT)
655
                    .setDefaultValue(Integer.valueOf(0))
656
                    .getIndex();
657

    
658
            ID_FIELD_PARENT = featureType.add(NAME_FIELD_PARENTID, DataTypes.INT)
659
                    .setDefaultValue(Integer.valueOf(0))
660
                    .getIndex();
661

    
662
            // FIXME: Cual es el size y el valor por defecto para Entity ?
663
            ID_FIELD_ENTITY = featureType.add(NAME_FIELD_ENTITY, DataTypes.STRING, 100)
664
                    .setDefaultValue("")
665
                    .getIndex();
666

    
667
            // FIXME: Cual es el size de Layer ?
668
            ID_FIELD_LEVEL = featureType.add(NAME_FIELD_LEVEL, DataTypes.STRING, 100)
669
                    .setDefaultValue("default")
670
                    .getIndex();
671
            ID_FIELD_LAYER = ID_FIELD_LEVEL;
672

    
673
            ID_FIELD_COLOR = featureType.add(NAME_FIELD_COLOR, DataTypes.INT)
674
                    .setDefaultValue(Integer.valueOf(0))
675
                    .getIndex();
676

    
677
            // FIXME: Cual es el size de Text ?
678
            ID_FIELD_TEXT = featureType.add(NAME_FIELD_TEXT, DataTypes.STRING, 100)
679
                    .setDefaultValue("")
680
                    .getIndex();
681

    
682
            ID_FIELD_HEIGHTTEXT = featureType.add(NAME_FIELD_HEIGHTTEXT, DataTypes.DOUBLE)
683
                    .setDefaultValue(Double.valueOf(10))
684
                    .getIndex();
685

    
686
            ID_FIELD_HEIGHTTEXTRAW = featureType.add(NAME_FIELD_HEIGHTTEXTRAW, DataTypes.DOUBLE)
687
                    .setDefaultValue(Double.valueOf(10))
688
                    .getIndex();
689

    
690
            ID_FIELD_ROTATIONTEXT = featureType.add(NAME_FIELD_ROTATIONTEXT, DataTypes.DOUBLE)
691
                    .setDefaultValue(Double.valueOf(0))
692
                    .getIndex();
693

    
694
            ID_FIELD_TYPE = featureType.add(NAME_FIELD_TYPE, DataTypes.INT)
695
                    .setDefaultValue(Integer.valueOf(0))
696
                    .getIndex();
697

    
698
            ID_FIELD_STYPE = featureType.add(NAME_FIELD_STYPE, DataTypes.INT)
699
                    .setDefaultValue(Integer.valueOf(0))
700
                    .getIndex();
701

    
702
            ID_FIELD_FILLCOLOR = featureType.add(NAME_FIELD_FILLCOLOR, DataTypes.INT)
703
                    .setDefaultValue(Integer.valueOf(0))
704
                    .getIndex();
705

    
706
            ID_FIELD_STYLE = featureType.add(NAME_FIELD_STYLE, DataTypes.INT)
707
                    .setDefaultValue(Integer.valueOf(0))
708
                    .getIndex();
709

    
710
            ID_FIELD_ELEVATION = featureType.add(NAME_FIELD_ELEVATION, DataTypes.DOUBLE)
711
                    .setDefaultValue(Double.valueOf(0))
712
                    .getIndex();
713

    
714
            ID_FIELD_WEIGHT = featureType.add(NAME_FIELD_WEIGHT, DataTypes.DOUBLE)
715
                    .setDefaultValue(Double.valueOf(0))
716
                    .getIndex();
717

    
718
            ID_FIELD_GROUP = featureType.add(NAME_FIELD_GROUP, DataTypes.INT)
719
                    .setDefaultValue(Integer.valueOf(0))
720
                    .getIndex();
721

    
722
            ID_FIELD_ISSHAPE = featureType.add(NAME_FIELD_ISSHAPE, DataTypes.BOOLEAN)
723
                    .setDefaultValue(Boolean.FALSE)
724
                    .getIndex();
725

    
726
            ID_FIELD_ISCOMPLEXSHAPEHEADER = featureType.add(NAME_FIELD_ISCOMPLEXSHAPEHEADER, DataTypes.BOOLEAN)
727
                    .setDefaultValue(Boolean.FALSE)
728
                    .getIndex();
729

    
730
            ID_FIELD_ISHOLE = featureType.add(NAME_FIELD_ISHOLE, DataTypes.BOOLEAN)
731
                    .setDefaultValue(Boolean.FALSE)
732
                    .getIndex();
733

    
734
            ID_FIELD_ISCOMPLEX = featureType.add(NAME_FIELD_ISCOMPLEX, DataTypes.BOOLEAN)
735
                    .setDefaultValue(Boolean.FALSE)
736
                    .getIndex();
737

    
738
            ID_FIELD_SCALE = featureType.add(NAME_FIELD_SCALE, DataTypes.INT)
739
                    .setDefaultValue(Integer.valueOf(0))
740
                    .getIndex();
741

    
742
            EditableFeatureAttributeDescriptor attr = featureType.add(NAME_FIELD_GEOMETRY, DataTypes.GEOMETRY);
743
            attr.setSRS(this.projection);
744
            int geometryTypeFilter = getDGNParameters().getGeometryTypeFilter();
745
            attr.setGeometryType(geometryTypeFilter);
746
            attr.setGeometrySubType(Geometry.SUBTYPES.GEOM3D);
747
            ID_FIELD_GEOMETRY = attr.getIndex();
748

    
749
            featureType.setDefaultGeometryAttributeName(NAME_FIELD_GEOMETRY);
750

    
751
            MAX_FIELD_ID = featureType.size() - 1;
752

    
753
            types = new ArrayList();
754
            types.add(featureType);
755

    
756
            if (leyendBuilder != null) {
757
                leyendBuilder.begin();
758
            }
759

    
760
        }
761

    
762
        public void end() {
763
            if (leyendBuilder != null) {
764
                leyendBuilder.end();
765
            }
766
        }
767

    
768
        public List getTypes() {
769
            return types;
770
        }
771

    
772
        public EditableFeatureType getDefaultType() {
773
            return (EditableFeatureType) types.get(0);
774
        }
775

    
776
//                private Double toDouble(String value) {
777
//                        if (value == null) {
778
//                                return Double.valueOf(0);
779
//                        }
780
//                        return Double.valueOf(value);
781
//                }
782
        public void load() throws DataException, CreateEnvelopeException {
783
            switch (getDGNParameters().getLoadMode()) {
784
                case LOAD_MODE_PLAIN:
785
                default:
786
                    load_plain();
787
                    break;
788
                case LOAD_MODE_GROUP1:
789
                    load_group1();
790
                    break;
791
            }
792
        }
793

    
794
        public void load_plain() throws DataException {
795

    
796
            FileWriter xmlfw = null;
797
            BufferedWriter xmlbfw = null;
798

    
799
            this.envelope = null;
800

    
801
            boolean ignoreZs = getDGNParameters().ignoreZs();
802
            boolean useZAsElevation = getDGNParameters().useZAsElevation();
803
            boolean applyRoundToElevation = getDGNParameters().getApplyRoundToElevation();
804
            double elevationFactor = getDGNParameters().geElevationFactor();
805
                    
806
            try {
807
                if (getDGNParameters().getXMLFile() != null) {
808
                    File xmlfile = getDGNParameters().getXMLFile();
809
                    try {
810
                        xmlfw = new FileWriter(xmlfile);
811
                        xmlbfw = new BufferedWriter(xmlfw);
812

    
813
                    } catch (Exception ex) {
814
                        xmlfw = null;
815
                        xmlbfw = null;
816
                        logger.warn("Can't open xmfile for output (" + xmlfile.getAbsolutePath() + "'.", ex);
817
                    }
818
                    if (xmlbfw != null) {
819
                        try {
820
                            xmlbfw.write("<DGN>\n");
821
                        } catch (IOException ex) {
822
                            logger.warn("Can't write to the xml file.", ex);
823
                        }
824
                    }
825

    
826
                }
827

    
828
                DGNReader dgnReader = new DGNReader(file.getAbsolutePath(), getDGNParameters().logErrors());
829

    
830
                if ( dgnReader.getInfo().dimension == 2 || getDGNParameters().ignoreZs() ) {
831
                    envelope = geomManager.createEnvelope(SUBTYPES.GEOM2D);
832
                } else {
833
                    envelope = geomManager.createEnvelope(SUBTYPES.GEOM3D);
834
                }
835
                
836
                FeatureType type = getDefaultType().getNotEditableCopy();
837

    
838
                filter = new Filter(getDGNParameters(), dgnReader);
839

    
840
                int counterOfElement = 0;
841
                DGNElemComplexHeader parentElement = null;
842
                
843
                double zvalue = 0;
844
                
845
                for (int id = 0; id < dgnReader.getNumEntities(); id++) {
846
                    dgnReader.DGNGotoElement(id);
847

    
848
                    DGNElemCore elemento = dgnReader.DGNReadElement();
849
                    if (elemento == null) {
850
                        continue;
851
                    }
852

    
853
                    if (parentElement != null) {
854
                        counterOfElement++;
855
                        if (parentElement.getNumElements() < counterOfElement) {
856
                            // Ya hemos terminado de recorrer el elemento complejo.
857
                            parentElement = null;
858
                        }
859
                    }
860

    
861
                    if (xmlbfw != null) {
862
                        // Volcamos el elemnto del DGN a fichero en formato XML
863
                        try {
864
                            xmlbfw.write(dgnReader.DGNDumpElement(dgnReader.getInfo(), elemento));
865
                        } catch (IOException ex) {
866
                            logger.warn("Can't write to the xml file.", ex);
867
                        }
868
                    }
869

    
870
                    if (elemento.isDeleted()) {
871
//                      Saltamos los elementos borrados.
872
                        continue;
873
                    }
874

    
875
                    FeatureProvider data = createFeatureProvider(type);
876

    
877
                    data.set(ID_FIELD_ID, elemento.getID());
878
                    data.set(ID_FIELD_TYPE, elemento.getType());
879
                    data.set(ID_FIELD_STYPE, elemento.getSType());
880
                    data.set(ID_FIELD_LEVEL, elemento.getLevelAsString());
881
                    data.set(ID_FIELD_COLOR, elemento.getColor());
882
                    data.set(ID_FIELD_FILLCOLOR, elemento.getShapeFillColor());
883
                    data.set(ID_FIELD_ENTITY, elemento.getEntityName());
884
                    data.set(ID_FIELD_STYLE, elemento.getStyle());
885
                    data.set(ID_FIELD_WEIGHT, elemento.getWeight());
886
                    data.set(ID_FIELD_GROUP, elemento.getGroup());
887
                    data.set(ID_FIELD_ELEVATION, elemento.getElevation());
888
                    data.set(ID_FIELD_ISCOMPLEXSHAPEHEADER, elemento.isComplexShapeHeader());
889
                    data.set(ID_FIELD_ISSHAPE, elemento.isShape());
890
                    data.set(ID_FIELD_ISHOLE, elemento.isHole());
891
                    data.set(ID_FIELD_ISCOMPLEX, elemento.isComplex());
892
                    data.set(ID_FIELD_HEIGHTTEXT, 0);
893
                    data.set(ID_FIELD_HEIGHTTEXTRAW, 0);
894
                    data.set(ID_FIELD_ROTATIONTEXT, 0);
895
                    data.set(ID_FIELD_TEXT, null);
896
                    data.set(ID_FIELD_SCALE, dgnReader.getInfo().scale);
897
                    if (parentElement == null) {
898
                        data.set(ID_FIELD_PARENT, elemento.getID());
899
                    } else {
900
                        data.set(ID_FIELD_PARENT, parentElement.getID());
901
                    }
902
                    zvalue = 0;
903
                    try {
904
                        switch (elemento.stype) {
905
                            case DGNFileHeader.DGNST_COMPLEX_HEADER:
906
                                parentElement = (DGNElemComplexHeader) elemento;
907
                                counterOfElement = 0;
908
                                break;
909

    
910
                            case DGNFileHeader.DGNST_MULTIPOINT:
911
                                DGNElemMultiPoint dgnmultipoint = (DGNElemMultiPoint) elemento;
912
                                if (dgnmultipoint.isPoint()) {
913
                                    DGNPoint p = dgnmultipoint.getPoint(0);
914
                                    Point point = createPoint3D(p.getX(), p.getY(), ignoreZs ? 0 : p.getZ());
915
                                    data.setDefaultGeometry(point);
916
                                    zvalue = p.getZ();
917
                                } else {
918
                                    OrientablePrimitive geom = null;
919
                                    if (dgnmultipoint.isPolygon()) {
920
                                        geom = geomManager.createSurface(
921
                                                dgnmultipoint.is3D()
922
                                                ? Geometry.SUBTYPES.GEOM3D
923
                                                : Geometry.SUBTYPES.GEOM2D
924
                                        );
925
                                    } else {
926
                                        geom = geomManager.createCurve(
927
                                                dgnmultipoint.is3D()
928
                                                ? Geometry.SUBTYPES.GEOM3D
929
                                                : Geometry.SUBTYPES.GEOM2D
930
                                        );
931
                                    }
932

    
933
                                    // Si es una curva nos saltamos los dos primeros y los dos ultimos vertices.
934
                                    int first = 0;
935
                                    int numVertices = dgnmultipoint.getNumVertices();
936
                                    if (dgnmultipoint.isCurve()) {
937
                                        first = 2;
938
                                        numVertices = dgnmultipoint.getNumVertices() - 2;
939
                                    }
940

    
941
                                    if (dgnmultipoint.isHole()) {
942
                                        // Invertimos el orden porque es un agujero
943
                                        for (int i = numVertices - 2; i >= first; i--) {
944
                                            DGNPoint p = dgnmultipoint.getVertex(i);
945
                                            zvalue = p.getZ();
946
                                            geom.addVertex(p.getX(), p.getY(), ignoreZs ? 0 : zvalue);
947
                                        }
948
                                    } else {
949
                                        for (int i = first; i < numVertices; i++) {
950
                                            DGNPoint p = dgnmultipoint.getVertex(i);
951
                                            zvalue = p.getZ();
952
                                            geom.addVertex(p.getX(), p.getY(), ignoreZs ? 0 : zvalue);
953
                                        }
954
                                    }
955
                                    data.setDefaultGeometry(geom);
956
                                }
957
                                break;
958

    
959
                            case DGNFileHeader.DGNST_ARC:
960
                                DGNElemArc dgnarc = (DGNElemArc) elemento;
961

    
962
                                // La definici?n de arco de MicroStation es distinta a
963
                                // la de Java.
964
                                // En el dgn el origin se entiende que es el centro del
965
                                // arco,
966
                                // y a la hora de crear un Arc2D las 2 primeras
967
                                // coordenadas son
968
                                // la esquina inferior izquierda del rect?ngulo que
969
                                // rodea al arco.
970
                                // 1.- Creamos la elipse sin rotaci?n.
971
                                // 2.- Creamos el arco
972
                                // 3.- Rotamos el resultado
973
                                AffineTransform mT = AffineTransform.getRotateInstance(
974
                                        Math.toRadians(dgnarc.rotation), dgnarc.origin.x,
975
                                        dgnarc.origin.y);
976

    
977
                                // mT.preConcatenate(AffineTransform.getScaleInstance(100.0,100.0));
978
                                Arc2D.Double elArco = new Arc2D.Double(
979
                                        dgnarc.origin.x - dgnarc.primary_axis,
980
                                        dgnarc.origin.y - dgnarc.secondary_axis,
981
                                        2.0 * dgnarc.primary_axis,
982
                                        2.0 * dgnarc.secondary_axis,
983
                                        -dgnarc.startang,
984
                                        -dgnarc.sweepang,
985
                                        Arc2D.OPEN);
986

    
987
                                zvalue = dgnarc.origin.getZ();
988
                                
989
                                GeneralPathX elShapeArc = new GeneralPathX(elArco.getPathIterator(null));
990

    
991
                                // Transformamos el GeneralPahtX porque si transformamos
992
                                // elArco nos lo convierte
993
                                // a GeneralPath y nos guarda las coordenadas en float,
994
                                // con la correspondiente p?rdida de precisi?n
995
                                elShapeArc.transform(mT);
996

    
997
                                Geometry geom = null;
998
                                if (dgnarc.isSurface()) {
999
                                    geom = geomManager.createSurface(elShapeArc,
1000
                                            dgnarc.is3D()
1001
                                            ? Geometry.SUBTYPES.GEOM3D
1002
                                            : Geometry.SUBTYPES.GEOM2D
1003
                                    );
1004
                                } else {
1005
                                    geom = geomManager.createCurve(elShapeArc,
1006
                                            dgnarc.is3D()
1007
                                            ? Geometry.SUBTYPES.GEOM3D
1008
                                            : Geometry.SUBTYPES.GEOM2D
1009
                                    );
1010
                                }
1011
                                data.setDefaultGeometry(geom);
1012
                                break;
1013

    
1014
                            case DGNFileHeader.DGNST_TEXT:
1015
                                DGNElemText dgntext = (DGNElemText) elemento;
1016
                                zvalue = dgntext.getPoint().getZ();
1017
                                Point point = createPoint3D(
1018
                                        dgntext.getPoint().getX(),
1019
                                        dgntext.getPoint().getY(),
1020
                                        ignoreZs ? 0 : zvalue
1021
                                );
1022
                                data.set(ID_FIELD_HEIGHTTEXT, dgntext.getHeight());
1023
                                data.set(ID_FIELD_HEIGHTTEXTRAW, dgntext.getRawHeight());
1024
                                data.set(ID_FIELD_ROTATIONTEXT, dgntext.getRotation());
1025
                                data.set(ID_FIELD_TEXT, dgntext.getText());
1026

    
1027
                                data.setDefaultGeometry(point);
1028
                                break;
1029

    
1030
                            default:
1031
                                break;
1032

    
1033
                        } // switch
1034
                    } catch (Exception ex) {
1035
                        logger.warn("Can't process element", ex);
1036
                    }
1037
                    if( useZAsElevation ) {
1038
                        if( !DGNStoreProvider.equals(elevationFactor, 1, 0.00001) ) {
1039
                            zvalue = zvalue*elevationFactor;
1040
                        }
1041
                        if( applyRoundToElevation ) {
1042
                            zvalue = Math.round(zvalue);
1043
                        }
1044
                        data.set(ID_FIELD_ELEVATION, zvalue);
1045
                    }
1046
                    addFeature(data, dgnReader);
1047
                } // for
1048

    
1049
                if (xmlbfw != null) {
1050
                    try {
1051
                        xmlbfw.write("</DGN>\n");
1052
                    } catch (IOException ex) {
1053
                        logger.warn("Can't write to the xml file.", ex);
1054
                    }
1055
                }
1056

    
1057
                consolideGroups(dgnReader);
1058
                if (getDGNParameters().sortByGeometryType()) {
1059
                    sortRows();
1060
                }
1061

    
1062
            } catch (Exception ex) {
1063
                logger.warn("Can't process DGN file", ex);
1064
            } finally {
1065
                IOUtils.closeQuietly(xmlbfw);
1066
                IOUtils.closeQuietly(xmlfw);
1067
            }
1068

    
1069
        }
1070

    
1071
        private void consolideGroups(DGNReader dgnReader) {
1072
            if (groupedFeatures == null) {
1073
                return;
1074
            }
1075
            boolean applyConvexHull = getDGNParameters().getApplyConvexHull();
1076
            FilteredLogger log = new FilteredLogger(logger, "ConsolideGroupBy", 10);
1077

    
1078
            Iterator<Map.Entry<Object, FeatureProvider>> it = groupedFeatures.entrySet().iterator();
1079
            while (it.hasNext()) {
1080
                Map.Entry<Object, FeatureProvider> entry = it.next();
1081
                String groupValue = "<null>";
1082
                if (entry.getKey() != null) {
1083
                    groupValue = entry.getKey().toString();
1084
                }
1085
                try {
1086
                    FeatureProvider data = entry.getValue();
1087
                    Geometry geometry = data.getDefaultGeometry();
1088
                    if (geometry != null) {
1089
                        if (applyConvexHull) {
1090
                            Geometry geom = (Geometry) data.get(ID_FIELD_GEOMETRY);
1091
                            try {
1092
                                data.set(ID_FIELD_GEOMETRY, geom.convexHull());
1093
                            } catch (Exception ex) {
1094
                                log.warn("Can't create convex-hull with geometries of the group '" + groupValue + "'.", ex);
1095
                            }
1096
                        }
1097
                        if (this.envelope == null) {
1098
                            this.envelope = geometry.getEnvelope();
1099
                        } else {
1100
                            this.envelope.add(geometry.getEnvelope());
1101
                        }
1102
                    }
1103
                    addFeatureProvider(data);
1104
                    if (this.leyendBuilder != null) {
1105
                        this.leyendBuilder.process(data, dgnReader);
1106
                    }
1107
                } catch (Exception ex) {
1108
                    log.warn("Problem adding data from group '"+groupValue+"'.", ex);
1109
                }
1110
            }
1111
        }
1112

    
1113
        private void fillRow(Object[] row, DGNElemCore elemento, DGNElemComplexHeader parentElement, DGNReader dgnReader) {
1114
            row[ID_FIELD_HEIGHTTEXT] = new Double(0);
1115
            row[ID_FIELD_HEIGHTTEXTRAW] = new Double(0);
1116
            row[ID_FIELD_ROTATIONTEXT] = new Double(0);
1117
            row[ID_FIELD_TEXT] = null;
1118

    
1119
            row[ID_FIELD_ID] = elemento.getID();
1120
            row[ID_FIELD_TYPE] = elemento.getType();
1121
            row[ID_FIELD_STYPE] = elemento.getSType();
1122
            row[ID_FIELD_LEVEL] = elemento.getLevelAsString();
1123
            row[ID_FIELD_COLOR] = elemento.getColor();
1124
            row[ID_FIELD_FILLCOLOR] = elemento.getShapeFillColor();
1125
            row[ID_FIELD_ENTITY] = elemento.getEntityName();
1126
            row[ID_FIELD_STYLE] = elemento.getStyle();
1127
            row[ID_FIELD_WEIGHT] = elemento.getWeight();
1128
            row[ID_FIELD_GROUP] = elemento.getGroup();
1129
            row[ID_FIELD_ELEVATION] = elemento.getElevation();
1130
            row[ID_FIELD_ISCOMPLEXSHAPEHEADER] = elemento.isComplexShapeHeader();
1131
            row[ID_FIELD_ISSHAPE] = elemento.isShape();
1132
            row[ID_FIELD_ISHOLE] = elemento.isHole();
1133
            row[ID_FIELD_ISCOMPLEX] = elemento.isComplex();
1134
            row[ID_FIELD_PARENT] = elemento.getID();
1135
            if (parentElement != null) {
1136
                row[ID_FIELD_PARENT] = parentElement.getID();
1137
            }
1138
            row[ID_FIELD_SCALE] = dgnReader.getInfo().scale;
1139

    
1140
        }
1141

    
1142
        public void load_group1() throws DataException, CreateEnvelopeException {
1143

    
1144
            this.envelope = null;
1145

    
1146
            FileWriter xmlfw = null;
1147
            BufferedWriter xmlbfw = null;
1148
            if (getDGNParameters().getXMLFile() != null) {
1149
                File xmlfile = getDGNParameters().getXMLFile();
1150
                try {
1151
                    xmlfw = new FileWriter(xmlfile);
1152
                    xmlbfw = new BufferedWriter(xmlfw);
1153

    
1154
                } catch (Exception ex) {
1155
                    xmlfw = null;
1156
                    xmlbfw = null;
1157
                    logger.warn("Can't open xmfile for output (" + xmlfile.getAbsolutePath() + "'.", ex);
1158
                }
1159
                if (xmlbfw != null) {
1160
                    try {
1161
                        xmlbfw.write("<DGN>\n");
1162
                    } catch (IOException ex) {
1163
                        logger.warn("Can't write to the xml file.", ex);
1164
                    }
1165
                }
1166

    
1167
            }
1168
            DGNReader dgnReader = new DGNReader(file.getAbsolutePath());
1169
            if ( dgnReader.getInfo().dimension == 2) {
1170
                envelope = geomManager.createEnvelope(Geometry.SUBTYPES.GEOM2D);
1171
            } else {
1172
                envelope = geomManager.createEnvelope(SUBTYPES.GEOM3D);
1173
            }
1174

    
1175
            FeatureType type = getDefaultType().getNotEditableCopy();
1176
            int fTypeSize = type.size();
1177
            Object[] auxRow = new Object[fTypeSize];
1178
            Object[] cellRow = new Object[fTypeSize];
1179
            Object[] complexRow = new Object[fTypeSize];
1180

    
1181
            boolean bElementoCompuesto = false;
1182
            boolean bEsPoligono = false;
1183
            boolean bInsideCell = false;
1184
            boolean bFirstHoleEntity = false;
1185
            boolean bConnect = false; // Se usa para que los pol?gonos cierren
1186
            // bien cuando son formas compuestas
1187
//                        int contadorSubElementos = 0;
1188
//                        int numSubElementos = 0;
1189
            int complex_index_fill_color = -1;
1190
            int nClass; // Para filtrar los elementos de construcci?n, etc.
1191
            GeneralPathX elementoCompuesto = new GeneralPathX(
1192
                    GeneralPathX.WIND_EVEN_ODD);
1193

    
1194
            int counterOfElement = 0;
1195
            DGNElemComplexHeader parentElement = null;
1196

    
1197
            filter = new Filter(getDGNParameters(), dgnReader);
1198

    
1199
            for (int id = 0; id < dgnReader.getNumEntities(); id++) {
1200
                dgnReader.DGNGotoElement(id);
1201

    
1202
                DGNElemCore elemento = dgnReader.DGNReadElement();
1203
                if (parentElement != null) {
1204
                    counterOfElement++;
1205
                    if (parentElement.getNumElements() < counterOfElement) {
1206
                        // Ya hemos terminado de recorrer el elemento complejo.
1207
                        parentElement = null;
1208
                    }
1209
                }
1210

    
1211
                if (xmlbfw != null && elemento != null) {
1212
                    // Volcamos el elemnto del DGN a fichero en formato XML
1213
                    try {
1214
                        xmlbfw.write(dgnReader.DGNDumpElement(dgnReader.getInfo(), elemento));
1215
                    } catch (IOException ex) {
1216
                        logger.warn("Can't write to the xml file.", ex);
1217
                    }
1218
                }
1219

    
1220
                nClass = 0;
1221
                fillRow(auxRow, elemento, parentElement, dgnReader);
1222
                auxRow[ID_FIELD_HEIGHTTEXT] = new Double(0);
1223
                auxRow[ID_FIELD_ROTATIONTEXT] = new Double(0);
1224
                auxRow[ID_FIELD_TEXT] = null;
1225

    
1226
                if (elemento.properties != 0) {
1227
                    nClass = elemento.properties & DGNFileHeader.DGNPF_CLASS;
1228
                }
1229

    
1230
                if ((elemento != null) && (elemento.deleted == 0)
1231
                        && (nClass == 0)) // Leer un elemento
1232
                {
1233

    
1234
                    // if ((elemento.element_id > 3800) && (elemento.element_id
1235
                    // < 3850))
1236
                    // dgnReader.DGNDumpElement(dgnReader.getInfo(),elemento,"");
1237
                    if ((elemento.stype == DGNFileHeader.DGNST_MULTIPOINT)
1238
                            || (elemento.stype == DGNFileHeader.DGNST_ARC)
1239
                            || (elemento.stype == DGNFileHeader.DGNST_CELL_HEADER)
1240
                            || (elemento.stype == DGNFileHeader.DGNST_SHARED_CELL_DEFN)
1241
                            || (elemento.stype == DGNFileHeader.DGNST_COMPLEX_HEADER)) {
1242
                        if (elemento.complex != 0) {
1243
                            bElementoCompuesto = true;
1244
                        } else {
1245
                            if (bElementoCompuesto) {
1246
                                if (bInsideCell) {
1247
                                    auxRow[ID_FIELD_ENTITY] = cellRow[ID_FIELD_ENTITY];
1248
                                } else {
1249
                                    auxRow = complexRow;
1250
                                }
1251
                                addShape(createMultiCurve(elementoCompuesto),
1252
                                        auxRow, type, dgnReader);
1253

    
1254
                                if (bEsPoligono) {
1255
                                    if (complex_index_fill_color != -1) {
1256
                                        auxRow[ID_FIELD_COLOR] = complex_index_fill_color;
1257
                                    }
1258

    
1259
                                    addShape(
1260
                                            createMultiSurface(elementoCompuesto),
1261
                                            auxRow, type, dgnReader);
1262
                                }
1263

    
1264
                                elementoCompuesto = new GeneralPathX(
1265
                                        GeneralPathX.WIND_EVEN_ODD);
1266
                            }
1267

    
1268
                            bElementoCompuesto = false;
1269
                            bEsPoligono = false;
1270
                            bConnect = false;
1271

    
1272
                            bInsideCell = false;
1273
                        }
1274
                    }
1275

    
1276
                    switch (elemento.stype) {
1277
                        case DGNFileHeader.DGNST_SHARED_CELL_DEFN:
1278
                            bInsideCell = true;
1279
                            fillRow(cellRow, elemento, parentElement, dgnReader);
1280
                            cellRow[ID_FIELD_ID] = elemento.element_id;
1281
                            cellRow[ID_FIELD_LAYER] = String.valueOf(elemento.level);
1282
                            cellRow[ID_FIELD_COLOR] = elemento.color;
1283
                            cellRow[ID_FIELD_ENTITY] = "Shared Cell";
1284

    
1285
                            break;
1286

    
1287
                        case DGNFileHeader.DGNST_CELL_HEADER:
1288
                            bInsideCell = true;
1289

    
1290
                            fillRow(cellRow, elemento, parentElement, dgnReader);
1291
                            cellRow[ID_FIELD_ID] = elemento.element_id;
1292
                            cellRow[ID_FIELD_LAYER] = String.valueOf(elemento.level);
1293
                            cellRow[ID_FIELD_COLOR] = elemento.color;
1294
                            cellRow[ID_FIELD_ENTITY] = "Cell";
1295
                            complex_index_fill_color = dgnReader
1296
                                    .DGNGetShapeFillInfo(elemento);
1297
                            break;
1298

    
1299
                        case DGNFileHeader.DGNST_COMPLEX_HEADER:
1300

    
1301
                            // bElementoCompuesto = true;
1302
//                                                contadorSubElementos = 0;
1303
                            DGNElemComplexHeader psComplexHeader = (DGNElemComplexHeader) elemento;
1304

    
1305
                            parentElement = psComplexHeader;
1306
                            counterOfElement = parentElement.getNumElements();
1307

    
1308
//                                                numSubElementos = psComplexHeader.numelems;
1309
                            fillRow(complexRow, elemento, parentElement, dgnReader);
1310
                            complexRow[ID_FIELD_ID] = elemento.element_id;
1311
                            complexRow[ID_FIELD_LAYER] = String.valueOf(elemento.level);
1312
                            complexRow[ID_FIELD_COLOR] = elemento.color;
1313
                            complexRow[ID_FIELD_ENTITY] = "Complex";
1314

    
1315
                            if (psComplexHeader.type == DGNFileHeader.DGNT_COMPLEX_SHAPE_HEADER) {
1316
                                bEsPoligono = true;
1317

    
1318
                                // Si es un agujero, no conectamos con el anterior
1319
                                if ((psComplexHeader.properties & 0x8000) != 0) {
1320
                                    bFirstHoleEntity = true;
1321
                                } else {
1322
                                    // Miramos si tiene color de relleno
1323
                                    // complex_index_fill_color = -1;
1324
                                    // if (elemento.attr_bytes > 0) {
1325
                                    complex_index_fill_color = dgnReader
1326
                                            .DGNGetShapeFillInfo(elemento);
1327

    
1328
                                    // }
1329
                                }
1330

    
1331
                                bConnect = true;
1332
                            } else {
1333
                                bEsPoligono = false;
1334
                                bConnect = false;
1335
                            }
1336

    
1337
                            break;
1338

    
1339
                        case DGNFileHeader.DGNST_MULTIPOINT:
1340

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

    
1361
                            if ((psLine.num_vertices == 2)
1362
                                    && (psLine.vertices[0].x == psLine.vertices[1].x)
1363
                                    && (psLine.vertices[0].y == psLine.vertices[1].y)) {
1364
                                auxRow[ID_FIELD_ENTITY] = "Point";
1365
                                addShape(
1366
                                        createPoint3D(psLine.vertices[0].x,
1367
                                                psLine.vertices[0].y,
1368
                                                psLine.vertices[0].z), auxRow,
1369
                                        type, dgnReader);
1370
                            } else {
1371
                                GeneralPathX elShape = new GeneralPathX(
1372
                                        GeneralPathX.WIND_EVEN_ODD);
1373

    
1374
                                if (psLine.type == DGNFileHeader.DGNT_CURVE) {
1375
                                    psLine.num_vertices = psLine.num_vertices - 4;
1376

    
1377
                                    for (int aux_n = 0; aux_n < psLine.num_vertices; aux_n++) {
1378
                                        psLine.vertices[aux_n] = psLine.vertices[aux_n + 2];
1379
                                    }
1380
                                }
1381

    
1382
                                if ((psLine.type == DGNFileHeader.DGNT_SHAPE)
1383
                                        && ((psLine.properties & 0x8000) != 0)) {
1384
                                    // Invertimos el orden porque es un agujero
1385
                                    elShape
1386
                                            .moveTo(
1387
                                                    psLine.vertices[psLine.num_vertices - 1].x,
1388
                                                    psLine.vertices[psLine.num_vertices - 1].y);
1389

    
1390
                                    for (int i = psLine.num_vertices - 2; i >= 0; i--) {
1391
                                        elShape.lineTo(psLine.vertices[i].x,
1392
                                                psLine.vertices[i].y);
1393
                                    }
1394
                                } else {
1395
                                    elShape.moveTo(psLine.vertices[0].x,
1396
                                            psLine.vertices[0].y);
1397

    
1398
                                    for (int i = 1; i < psLine.num_vertices; i++) {
1399
                                        elShape.lineTo(psLine.vertices[i].x,
1400
                                                psLine.vertices[i].y);
1401
                                    }
1402
                                }
1403

    
1404
                                if ((psLine.vertices[0].x == psLine.vertices[psLine.num_vertices - 1].x)
1405
                                        && (psLine.vertices[0].y == psLine.vertices[psLine.num_vertices - 1].y)) {
1406
                                    // Lo a?adimos tambi?n como pol?gono
1407
                                    bEsPoligono = true;
1408

    
1409
                                    // Miramos si tiene color de relleno
1410
                                    if (elemento.attr_bytes > 0) {
1411
                                        elemento.color = dgnReader
1412
                                                .DGNGetShapeFillInfo(elemento);
1413

    
1414
                                        if (elemento.color != -1) {
1415
                                            auxRow[ID_FIELD_COLOR] = elemento.color;
1416
                                        }
1417
                                    }
1418

    
1419
                                    if (elemento.complex == 0) {
1420
                                        addShape(createSurface(elShape), auxRow,
1421
                                                type, dgnReader);
1422
                                    }
1423
                                }
1424

    
1425
                                if (elemento.complex != 0) {
1426
                                    // Si es un agujero o
1427
                                    // es la primera entidad del agujero, lo
1428
                                    // a?adimos sin unir al anterior
1429
                                    if (bFirstHoleEntity
1430
                                            || ((psLine.type == DGNFileHeader.DGNT_SHAPE) && ((psLine.properties & 0x8000) != 0))) {
1431
                                        elementoCompuesto.append(elShape.getPathIterator(null), false);
1432
                                        bFirstHoleEntity = false;
1433
                                    } else {
1434
                                        elementoCompuesto.append(elShape.getPathIterator(null), bConnect);
1435
                                    }
1436
                                } else {
1437
                                    addShape(createMultiCurve(elShape), auxRow,
1438
                                            type, dgnReader);
1439
                                }
1440
                            }
1441

    
1442
                            break;
1443

    
1444
                        case DGNFileHeader.DGNST_ARC:
1445

    
1446
                            // dgnReader.DGNDumpElement(dgnReader.getInfo(),
1447
                            // elemento,"");
1448
                            DGNElemArc psArc = (DGNElemArc) elemento;
1449

    
1450
                            // La definici?n de arco de MicroStation es distinta a
1451
                            // la de Java.
1452
                            // En el dgn el origin se entiende que es el centro del
1453
                            // arco,
1454
                            // y a la hora de crear un Arc2D las 2 primeras
1455
                            // coordenadas son
1456
                            // la esquina inferior izquierda del rect?ngulo que
1457
                            // rodea al arco.
1458
                            // 1.- Creamos la elipse sin rotaci?n.
1459
                            // 2.- Creamos el arco
1460
                            // 3.- Rotamos el resultado
1461
                            AffineTransform mT = AffineTransform.getRotateInstance(
1462
                                    Math.toRadians(psArc.rotation), psArc.origin.x,
1463
                                    psArc.origin.y);
1464

    
1465
                            // mT.preConcatenate(AffineTransform.getScaleInstance(100.0,100.0));
1466
                            Arc2D.Double elArco = new Arc2D.Double(psArc.origin.x
1467
                                    - psArc.primary_axis, psArc.origin.y
1468
                                    - psArc.secondary_axis,
1469
                                    2.0 * psArc.primary_axis,
1470
                                    2.0 * psArc.secondary_axis, -psArc.startang,
1471
                                    -psArc.sweepang, Arc2D.OPEN);
1472

    
1473
                            // Ellipse2D.Double elArco = new
1474
                            // Ellipse2D.Double(psArc.origin.x - psArc.primary_axis,
1475
                            // psArc.origin.y - psArc.secondary_axis,2.0 *
1476
                            // psArc.primary_axis, 2.0 * psArc.secondary_axis);
1477
                            GeneralPathX elShapeArc = new GeneralPathX(elArco.getPathIterator(null));
1478

    
1479
                            // Transformamos el GeneralPahtX porque si transformamos
1480
                            // elArco nos lo convierte
1481
                            // a GeneralPath y nos guarda las coordenadas en float,
1482
                            // con la correspondiente p?rdida de precisi?n
1483
                            elShapeArc.transform(mT);
1484

    
1485
                            if (dgnReader.getInfo().dimension == 3) {
1486
                                // Aqu? podr?amos hacer cosas con la coordenada Z
1487
                            }
1488

    
1489
                            fillRow(auxRow, elemento, parentElement, dgnReader);
1490
                            auxRow[ID_FIELD_ID] = elemento.element_id;
1491
                            auxRow[ID_FIELD_ENTITY] = "Arc";
1492
                            auxRow[ID_FIELD_LAYER] = String.valueOf(elemento.level);
1493
                            auxRow[ID_FIELD_COLOR] = elemento.color;
1494

    
1495
                            /*
1496
                             * Line2D.Double ejeMayor = new
1497
                             * Line2D.Double(psArc.origin.x - psArc.primary_axis,
1498
                             * psArc.origin.y, psArc.origin.x + psArc.primary_axis,
1499
                             * psArc.origin.y);
1500
                             *
1501
                             * lyrLines.addShape(new
1502
                             * FShape(FConstant.SHAPE_TYPE_POLYLINE, new
1503
                             * GeneralPathX(ejeMayor)), auxRow);
1504
                             */
1505
                            // lyrLines.addShape(new
1506
                            // FShape(FConstant.SHAPE_TYPE_POLYLINE, elShapeArc),
1507
                            // auxRow);
1508
                            if (elemento.complex != 0) {
1509
                                // Esto es una posible fuente de fallos si detr?s de
1510
                                // una
1511
                                // elipse vienen m?s cosas pegadas. Deber?amos
1512
                                // volver
1513
                                // a conectar una vez pasada la elipse.
1514
                                if (elemento.type == DGNFileHeader.DGNT_ELLIPSE) {
1515
                                    bConnect = false;
1516
                                }
1517

    
1518
                                // SI LA ELIPSE ES UN AGUJERO, SE A?ADE SIN PEGAR
1519
                                // Y EL ELEMENTO ES UN POLIGONO
1520
                                if (bFirstHoleEntity
1521
                                        || ((elemento.type == DGNFileHeader.DGNT_SHAPE) && ((elemento.properties & 0x8000) != 0))) {
1522
                                    elementoCompuesto.append(elShapeArc.getPathIterator(null), false);
1523
                                    bFirstHoleEntity = false;
1524
                                } else {
1525
                                    elementoCompuesto.append(elShapeArc.getPathIterator(null), bConnect);
1526
                                }
1527
                            } else {
1528
                                addShape(createMultiCurve(elShapeArc), auxRow,
1529
                                        type, dgnReader);
1530

    
1531
                                if (psArc.type == DGNFileHeader.DGNT_ELLIPSE) {
1532
                                    addShape(createSurface(elShapeArc), auxRow,
1533
                                            type, dgnReader);
1534
                                }
1535
                            }
1536

    
1537
                            break;
1538

    
1539
                        case DGNFileHeader.DGNST_TEXT:
1540

    
1541
                            DGNElemText psText = (DGNElemText) elemento;
1542
                            Geometry elShapeTxt = createPoint3D(psText.origin.x,
1543
                                    psText.origin.y, psText.origin.z);
1544

    
1545
                            fillRow(auxRow, elemento, parentElement, dgnReader);
1546
                            auxRow[ID_FIELD_ID] = elemento.element_id;
1547
                            auxRow[ID_FIELD_ENTITY] = "Text";
1548
                            auxRow[ID_FIELD_LAYER] = String.valueOf(elemento.level);
1549
                            auxRow[ID_FIELD_COLOR] = elemento.color;
1550
                            auxRow[ID_FIELD_HEIGHTTEXT] = psText.height_mult;
1551
                            auxRow[ID_FIELD_HEIGHTTEXTRAW] = psText.height_raw;
1552
                            auxRow[ID_FIELD_ROTATIONTEXT] = psText.rotation;
1553
                            auxRow[ID_FIELD_TEXT] = psText.string; // .trim();
1554
                            addShape(elShapeTxt, auxRow, type, dgnReader);
1555
                            break;
1556

    
1557
                        /*
1558
                         * default:
1559
                         * dgnReader.DGNDumpElement(dgnReader.getInfo(),
1560
                         * elemento, "");
1561
                         */
1562
                    } // switch
1563
                } // if
1564
            } // for
1565

    
1566
            if (bElementoCompuesto) {
1567
                if (bInsideCell) {
1568
                    auxRow = cellRow;
1569
                } else {
1570
                    auxRow = complexRow;
1571
                }
1572

    
1573
                addShape(createMultiCurve(elementoCompuesto), auxRow, type,
1574
                        dgnReader);
1575

    
1576
                if (bEsPoligono) {
1577
                    if (complex_index_fill_color != -1) {
1578
                        auxRow[ID_FIELD_COLOR] = complex_index_fill_color;
1579
                    }
1580

    
1581
                    addShape(createSurface(elementoCompuesto), auxRow, type,
1582
                            dgnReader);
1583
                }
1584
            }
1585

    
1586
            if (xmlbfw != null) {
1587
                try {
1588
                    xmlbfw.write("</DGN>\n");
1589
                } catch (IOException ex) {
1590
                    logger.warn("Can't write to the xml file.", ex);
1591
                }
1592
                IOUtils.closeQuietly(xmlbfw);
1593
                IOUtils.closeQuietly(xmlfw);
1594
            }
1595

    
1596
        }
1597

    
1598
        private Geometry createMultiSurface(GeneralPathX elementoCompuesto)
1599
                throws DataException {
1600
            try {
1601
                return geomManager.createMultiSurface(elementoCompuesto,
1602
                        SUBTYPES.GEOM2D);
1603
            } catch (CreateGeometryException e) {
1604
                throw new org.gvsig.fmap.dal.feature.exception.CreateGeometryException(
1605
                        e);
1606
            }
1607

    
1608
        }
1609

    
1610
        private Curve createCurve(boolean is3D) throws CreateGeometryException {
1611
            if (is3D) {
1612
                return (Curve) geomManager.create(
1613
                        Geometry.TYPES.CURVE,
1614
                        Geometry.SUBTYPES.GEOM3D);
1615
            }
1616
            return (Curve) geomManager.create(
1617
                    Geometry.TYPES.CURVE,
1618
                    Geometry.SUBTYPES.GEOM2D);
1619

    
1620
        }
1621

    
1622
        private Point createPoint3D(double x, double y, double z)
1623
                throws DataException {
1624
            Point point;
1625
            try {
1626
                // point = (Point) geomManager.create(TYPES.POINT,
1627
                // SUBTYPES.GEOM3D);
1628
                point = (Point) geomManager.create(TYPES.POINT,
1629
                        SUBTYPES.GEOM3D);
1630
            } catch (CreateGeometryException e) {
1631
                throw new org.gvsig.fmap.dal.feature.exception.CreateGeometryException(
1632
                        e);
1633
            }
1634
            point.setCoordinates(new double[]{x, y, z});
1635

    
1636
            return point;
1637
        }
1638

    
1639
        private int getGroupByFieldIndex() {
1640
            if (groupByFieldIndex > -2) {
1641
                return groupByFieldIndex;
1642
            }
1643
            String groupby = getDGNParameters().getGroupBy();
1644
            if (groupby == null) {
1645
                groupByFieldIndex = -1;
1646
                return groupByFieldIndex;
1647
            }
1648
            groupByFieldIndex = this.getDefaultType().getIndex(groupby);
1649
            return groupByFieldIndex;
1650
        }
1651

    
1652
        private MultiPrimitive getMultiPrimitive(Geometry geom) {
1653
            if (geom == null) {
1654
                return null;
1655
            }
1656
            if (geom instanceof MultiPrimitive) {
1657
                return (MultiPrimitive) geom;
1658
            }
1659
            MultiPrimitive multi = null;
1660
            try {
1661
                if (geom instanceof Point) {
1662
                    multi = (MultiPrimitive) geomManager.create(
1663
                            TYPES.MULTIPOINT,
1664
                            geom.getGeometryType().getSubType()
1665
                    );
1666
                } else if (geom instanceof Curve) {
1667
                    multi = (MultiPrimitive) geomManager.create(
1668
                            TYPES.MULTICURVE,
1669
                            geom.getGeometryType().getSubType()
1670
                    );
1671
                } else if (geom instanceof Surface) {
1672
                    multi = (MultiPrimitive) geomManager.create(
1673
                            TYPES.MULTISURFACE,
1674
                            geom.getGeometryType().getSubType()
1675
                    );
1676
                }
1677
                if (multi != null) {
1678
                    multi.addPrimitive((Primitive) geom);
1679
                }
1680
            } catch (CreateGeometryException ex) {
1681
                logger.warn("Can't create multi-geometry to group", ex);
1682
            }
1683
            return multi;
1684
        }
1685

    
1686
        private void addToGroup(int groupbyField, FeatureProvider data) {
1687
            if (groupedFeatures == null) {
1688
                groupedFeatures = new HashMap<Object, FeatureProvider>();
1689
            }
1690
            Object groupbyValue = data.get(groupbyField);
1691
            FeatureProvider group = groupedFeatures.get(groupbyValue);
1692
            if (group == null) {
1693
                groupedFeatures.put(groupbyValue, data);
1694
                MultiPrimitive multi = getMultiPrimitive((Geometry) data.get(ID_FIELD_GEOMETRY));
1695
                if (multi == null) {
1696
                    data.set(ID_FIELD_GEOMETRY, null);
1697
                } else {
1698
                    data.set(ID_FIELD_GEOMETRY, multi);
1699
                }
1700
                return;
1701
            }
1702
            for (int i = 0; i <= MAX_FIELD_ID; i++) {
1703
                Object value = group.get(i);
1704
                if (i == ID_FIELD_GEOMETRY) {
1705
                    Geometry newgeom = (Geometry) data.get(i);
1706
                    if (newgeom != null) {
1707
                        if (value == null) {
1708
                            group.set(ID_FIELD_GEOMETRY, getMultiPrimitive(newgeom));
1709
                        } else {
1710
                            try {
1711
                                ((MultiPrimitive) value).addPrimitive((Primitive) newgeom);
1712
                            } catch (Exception ex) {
1713
                                logger.warn("Can't group geoemtry '" + newgeom.toString() + "' in '" + value.toString() + "'.", ex);
1714
                            }
1715
                        }
1716
                    }
1717
                } else if (value == null) {
1718
                    group.set(i, data.get(i));
1719
                } else if (value instanceof String) {
1720
                    String s = (String) value;
1721
                    if (s.trim().length() == 0) {
1722
                        group.set(i, data.get(i));
1723
                    }
1724
                }
1725
            }
1726

    
1727
        }
1728

    
1729
        private void addFeature(FeatureProvider data, DGNReader dgnReader) throws DataException {
1730

    
1731
            if (!filter.accept(data)) {
1732
                return;
1733
            }
1734
            int groupByIndex = this.getGroupByFieldIndex();
1735
            if (groupByIndex >= 0) {
1736
                addToGroup(groupByIndex, data);
1737
                return;
1738
            }
1739
            addFeatureProvider(data);
1740
            Geometry geometry = data.getDefaultGeometry();
1741
            if (geometry != null) {
1742
                if (this.envelope == null) {
1743
                    this.envelope = geometry.getEnvelope();
1744
                } else {
1745
                    this.envelope.add(geometry.getEnvelope());
1746
                }
1747
            }
1748
            if (this.leyendBuilder != null) {
1749
                this.leyendBuilder.process(data, dgnReader);
1750
            }
1751
        }
1752

    
1753
        private void addShape(Geometry geometry, Object[] auxRow,
1754
                FeatureType type, DGNReader dgnReader) throws DataException {
1755

    
1756
            FeatureProvider data = createFeatureProvider(type);
1757
            for (int i = 0; i < type.size(); i++) {
1758
                data.set(i, auxRow[i]);
1759
            }
1760
            data.setDefaultGeometry(geometry);
1761
            addFeature(data, dgnReader);
1762
        }
1763

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

    
1775
        private Geometry createSurface(GeneralPathX elementoCompuesto)
1776
                throws DataException {
1777
            try {
1778
                return geomManager.createCurve(elementoCompuesto,
1779
                        SUBTYPES.GEOM2D);
1780
            } catch (CreateGeometryException e) {
1781
                throw new org.gvsig.fmap.dal.feature.exception.CreateGeometryException(
1782
                        e);
1783
            }
1784

    
1785
        }
1786

    
1787
    }
1788

    
1789
    public boolean closeResourceRequested(ResourceProvider resource) {
1790
        return true;
1791
    }
1792

    
1793
    public int getOIDType() {
1794
        return DataTypes.LONG;
1795
    }
1796

    
1797
    public boolean supportsAppendMode() {
1798
        return false;
1799
    }
1800

    
1801
    public void append(FeatureProvider featureProvider) {
1802
        throw new UnsupportedOperationException();
1803
    }
1804

    
1805
    public void beginAppend() {
1806
        throw new UnsupportedOperationException();
1807
    }
1808

    
1809
    public void endAppend() {
1810
        throw new UnsupportedOperationException();
1811
    }
1812

    
1813
    public Object createNewOID() {
1814
        return new Long(counterNewsOIDs++);
1815
    }
1816

    
1817
    protected void initializeFeatureTypes() throws InitializeException {
1818
        try {
1819
            this.open();
1820
        } catch (OpenException e) {
1821
            throw new InitializeException(this.getProviderName(), e);
1822
        }
1823
    }
1824

    
1825
    public Envelope getEnvelope() throws DataException {
1826
        this.open();
1827
        return (Envelope) this.getDynValue("Envelope");
1828
    }
1829

    
1830

    
1831
    /*
1832
     * (non-Javadoc)
1833
     *
1834
     * @see
1835
     * org.gvsig.fmap.dal.resource.spi.ResourceConsumer#resourceChanged(org.
1836
     * gvsig.fmap.dal.resource.spi.ResourceProvider)
1837
     */
1838
    public void resourceChanged(ResourceProvider resource) {
1839
        this.getStoreServices().notifyChange(
1840
                DataStoreNotification.RESOURCE_CHANGED,
1841
                resource);
1842
    }
1843

    
1844
    public Object getSourceId() {
1845
        return this.getDGNParameters().getFile();
1846
    }
1847

    
1848
    public String getName() {
1849
        String name = this.getDGNParameters().getFile().getName();
1850
        int n = name.lastIndexOf(".");
1851
        if (n < 1) {
1852
            return name;
1853
        }
1854
        return name.substring(0, n);
1855
    }
1856

    
1857
    public String getFullName() {
1858
        return this.getDGNParameters().getFile().getAbsolutePath();
1859
    }
1860

    
1861
    public ResourceProvider getResource() {
1862
        return resource;
1863
    }
1864

    
1865
    public static boolean equals(double a, double b, double precision) {
1866
        double v = Math.abs(a-b);
1867
        return v < precision;
1868
    }
1869
}