Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.mapcontext / org.gvsig.fmap.mapcontext.api / src / main / java / org / gvsig / fmap / mapcontext / layers / vectorial / FLyrVect.java @ 47455

History | View | Annotate | Download (56.5 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.fmap.mapcontext.layers.vectorial;
24

    
25
import java.awt.Graphics2D;
26
import java.awt.Point;
27
import java.awt.geom.AffineTransform;
28
import java.awt.geom.Point2D;
29
import java.awt.image.BufferedImage;
30
import java.io.File;
31
import java.util.Iterator;
32
import java.util.Set;
33
import java.util.TreeSet;
34
import org.cresques.cts.ICoordTrans;
35
import org.cresques.cts.IProjection;
36
import org.gvsig.compat.print.PrintAttributes;
37
import org.gvsig.fmap.dal.DALLocator;
38
import org.gvsig.fmap.dal.DataManager;
39
import org.gvsig.fmap.dal.DataStore;
40
import org.gvsig.fmap.dal.DataStoreParameters;
41
import org.gvsig.fmap.dal.exception.DataException;
42
import org.gvsig.fmap.dal.exception.InitializeException;
43
import org.gvsig.fmap.dal.exception.ReadException;
44
import org.gvsig.fmap.dal.feature.Feature;
45
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
46
import org.gvsig.fmap.dal.feature.FeatureQuery;
47
import org.gvsig.fmap.dal.feature.FeatureSet;
48
import org.gvsig.fmap.dal.feature.FeatureStore;
49
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
50
import org.gvsig.fmap.dal.feature.FeatureType;
51
import org.gvsig.fmap.dal.feature.OpenFeatureStoreParameters;
52
import org.gvsig.fmap.dal.feature.exception.CreateGeometryException;
53
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemStoreParameters;
54
import org.gvsig.fmap.geom.Geometry;
55
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
56
import org.gvsig.fmap.geom.Geometry.TYPES;
57
import org.gvsig.fmap.geom.GeometryLocator;
58
import org.gvsig.fmap.geom.GeometryManager;
59
import org.gvsig.fmap.geom.primitive.Circle;
60
import org.gvsig.fmap.geom.primitive.Envelope;
61
import org.gvsig.fmap.geom.type.GeometryType;
62
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
63
import org.gvsig.fmap.geom.type.GeometryTypeNotValidException;
64
import org.gvsig.fmap.mapcontext.MapContext;
65
import org.gvsig.fmap.mapcontext.MapContextLocator;
66
import org.gvsig.fmap.mapcontext.MapContextManager;
67
import org.gvsig.fmap.mapcontext.ViewPort;
68
import org.gvsig.fmap.mapcontext.exceptions.LegendLayerException;
69
import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
70
import org.gvsig.fmap.mapcontext.exceptions.ReloadLayerException;
71
import org.gvsig.fmap.mapcontext.exceptions.StartEditionLayerException;
72
import org.gvsig.fmap.mapcontext.layers.FLayer;
73
import org.gvsig.fmap.mapcontext.layers.FLayerStatus;
74
import org.gvsig.fmap.mapcontext.layers.FLyrDefault;
75
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
76
import org.gvsig.fmap.mapcontext.layers.LayerInformationBuilder;
77
import org.gvsig.fmap.mapcontext.layers.LayerListener;
78
import org.gvsig.fmap.mapcontext.layers.SelectionEvent;
79
import org.gvsig.fmap.mapcontext.layers.SelectionListener;
80
import org.gvsig.fmap.mapcontext.layers.SpatialCache;
81
import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
82
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
83
import org.gvsig.fmap.mapcontext.rendering.legend.LegendException;
84
import org.gvsig.fmap.mapcontext.rendering.legend.events.FeatureDrawnNotification;
85
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
86
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendClearEvent;
87
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendContentsChangedListener;
88
import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
89
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingStrategy;
90
import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
91
import org.gvsig.metadata.exceptions.MetadataException;
92
import org.gvsig.tools.ToolsLocator;
93
import org.gvsig.tools.dynobject.DynObjectManager;
94
import org.gvsig.tools.dynobject.DynObjectSet;
95
import org.gvsig.tools.dynobject.DynStruct;
96
import org.gvsig.tools.dynobject.Tags;
97
import org.gvsig.tools.evaluator.Evaluator;
98
import org.gvsig.tools.exception.BaseException;
99
import org.gvsig.tools.locator.LocatorException;
100
import org.gvsig.tools.observer.Observable;
101
import org.gvsig.tools.observer.Observer;
102
import org.gvsig.tools.persistence.PersistenceManager;
103
import org.gvsig.tools.persistence.PersistentState;
104
import org.gvsig.tools.persistence.exception.PersistenceException;
105
import org.gvsig.tools.task.Cancellable;
106
import org.gvsig.tools.util.Callable;
107
import org.gvsig.tools.visitor.VisitCanceledException;
108
import org.gvsig.tools.visitor.Visitor;
109
import org.slf4j.LoggerFactory;
110

    
111
/**
112
 * Capa b?sica Vectorial.
113
 *
114
 */
115
@SuppressWarnings("UseSpecificCatch")
116
public class FLyrVect
117
        extends FLyrDefault
118
        implements VectorLayer,
119
        LegendContentsChangedListener, Observer {
120

    
121
    public static final String TAG_LAYERVECT_MAXSCALE = "layervect.scale.max";
122
    public static final String TAG_LAYERVECT_MINSCALE = "layervect.scale.min";
123
    
124
    final static private org.slf4j.Logger logger
125
            = LoggerFactory.getLogger(FLyrVect.class);
126
    private final GeometryManager geomManager
127
            = GeometryLocator.getGeometryManager();
128

    
129
    /**
130
     * Leyenda de la capa vectorial
131
     */
132
    private IVectorLegend legend;
133
    private int typeShape = -1;
134
    private FeatureStore featureStore = null;
135
    private DataStoreParameters dataStoreParameters;
136
    private SpatialCache spatialCache = new SpatialCache();
137

    
138
    /**
139
     * An implementation of gvSIG spatial index
140
     */
141
    // protected ISpatialIndex spatialIndex = null;
142
    private IVectorLegend loadLegend = null;
143

    
144
    private boolean isLabeled;
145
    protected ILabelingStrategy strategy;
146
//        private ReprojectDefaultGeometry reprojectTransform;
147
    private FeatureQuery baseQuery = null;
148

    
149
    public FLyrVect() {
150
        super();
151
    }
152

    
153
    @Override
154
    public String getTocImageIcon() {
155
        if( this.featureStore==null && this.dataStoreParameters!=null ) {
156
            return MapContextLocator.getMapContextManager().getIconLayer(this.dataStoreParameters.getProviderName());
157
        }
158
        return MapContextLocator.getMapContextManager().getIconLayer(this.getDataStore());
159
    }
160

    
161
    /**
162
     * Return the store associated to the layer.
163
     *
164
     * @return the store
165
     */
166
    @Override
167
    public DataStore getDataStore() {
168
        return featureStore;
169
    }
170

    
171
    /**
172
     * Asigna el data-store a la capa. Esta operacion no se deneria poder hacer
173
     * desde fuera de la clase.
174
     *
175
     * @param dataStore
176
     * @throws LoadLayerException
177
     * @deprecated use {@link #bindToDataStore(DataStore)}
178
     */
179
    public void setDataStore(DataStore dataStore) throws LoadLayerException {
180
        bindToDataStore(dataStore);
181
    }
182

    
183
    public void setDataStoreParameters(DataStoreParameters parameters) {
184
        this.dataStoreParameters = parameters;
185
    }
186

    
187
    @Override
188
    public void setVisible(boolean visibility) {
189
        if( visibility && this.featureStore==null && this.dataStoreParameters!=null )  {
190
            try {
191
                DataManager dataManager = DALLocator.getDataManager();
192
                DataStore dataStore = dataManager.openStore(
193
                        this.dataStoreParameters.getProviderName(),
194
                        this.dataStoreParameters
195
                );
196
                this.bindToDataStore(dataStore);
197
                IProjection projection = (IProjection) dataStore.getDynValue(FeatureStore.METADATA_CRS);
198
                if (projection != null) {
199
                    this.setProjection(projection);
200
                }
201
                if (projection != null && this.getMapContext() != null) {
202
                    IProjection mapContextProj = this.getMapContext().getProjection();
203
                    if (!projection.getAbrev().equals(mapContextProj.getAbrev())) {
204
                        ICoordTrans ct = projection.getCT(mapContextProj);
205
                        this.setCoordTrans(ct);
206
                    } else {
207
                        this.setCoordTrans(null);
208
                    }
209
                }
210

    
211
            } catch (Exception ex) {
212
                throw new RuntimeException("Can't set visibility to layer", ex);
213
            }
214
        }
215
        super.setVisible(visibility);         
216
    }
217
    
218
    /**
219
     * Enlaza la capa con el DataStore indicado.
220
     *
221
     * @param dataStore
222
     * @throws LoadLayerException
223
     */
224
    protected void bindToDataStore(DataStore dataStore) throws LoadLayerException {
225
        if (this.featureStore != null && this.featureStore != dataStore) {
226
            this.featureStore.deleteObserver(this);
227
        }
228

    
229
        featureStore = (FeatureStore) dataStore;
230
        if( this.dataStoreParameters==null ) {
231
            this.dataStoreParameters = this.featureStore.getParameters();
232
        }
233
        
234
        MapContextManager mapContextManager
235
                = MapContextLocator.getMapContextManager();
236

    
237
        //Set the legend
238
        IVectorLegend legend
239
                = (IVectorLegend) mapContextManager.getLegend(dataStore);
240

    
241
        if (legend == null) {
242
            throw new LegendLayerException(this.getName());
243
        }
244

    
245
        this.setLegend(legend);
246

    
247
        //Set the labeling strategy
248
        ILabelingStrategy labeler
249
                = (ILabelingStrategy) mapContextManager.getLabelingStrategy(dataStore);
250

    
251
        if (labeler != null) {
252
            labeler.setLayer(this);
253
            this.setLabelingStrategy(labeler);
254
            this.setIsLabeled(true); // TODO: ac? no s'hauria de detectar si t?
255
            // etiquetes?????
256
        }
257

    
258
        this.delegate(dataStore);
259

    
260
        dataStore.addObserver(this);
261
        
262
        FeatureType featureType = featureStore.getDefaultFeatureTypeQuietly();
263
        if( featureType!=null ) {
264
            Tags tags = featureType.getTags();
265
            if( tags.has(TAG_LAYERVECT_MAXSCALE) ) {
266
                this.setMaxScale(tags.getInt(TAG_LAYERVECT_MAXSCALE, -1));
267
            }
268
            if( tags.has(TAG_LAYERVECT_MINSCALE) ) {
269
                this.setMinScale(tags.getInt(TAG_LAYERVECT_MINSCALE, -1));
270
            }
271
        }
272

    
273
        ToolsLocator.getDisposableManager().bind(dataStore);
274
    }
275
    
276
    
277

    
278
    public Envelope getFullEnvelope() throws ReadException {
279
        Envelope rAux;
280
        if (getFeatureStore() == null) {
281
            return null;
282
        }
283
        try {
284
            rAux = getFeatureStore().getEnvelope();
285
        } catch (BaseException e) {
286
            throw new ReadException(getName(), e);
287
        }
288

    
289
        // Esto es para cuando se crea una capa nueva con el fullExtent de ancho
290
        // y alto 0.
291
        if (rAux == null || rAux.isEmpty() ) {
292
            return rAux;
293
        }
294
        // Si existe reproyecci?n, reproyectar el extent
295
        ICoordTrans ct = getCoordTrans();
296
        if (ct != null) {
297
            rAux = rAux.convert(ct);
298
            if (rAux==null || rAux.isEmpty() ) {
299
                try {
300
                    this.setAvailable(false);
301
                    throw new EnvelopeCantBeInitializedException();
302
                } catch (EnvelopeCantBeInitializedException e) {
303
                    this.addError(e);
304
                }
305
            }
306
        }
307
        return rAux;
308

    
309
    }
310

    
311
    public void setBaseQuery(FeatureQuery baseQuery) {
312
        this.baseQuery = baseQuery;
313
    }
314

    
315
    @Override
316
    public FeatureQuery getBaseQuery() {
317
        return this.baseQuery;
318
    }
319

    
320
    public void addBaseFilter(Evaluator filter) {
321
        if (this.baseQuery == null) {
322
            this.baseQuery = this.getFeatureStore().createFeatureQuery();
323
        }
324
        this.baseQuery.addFilter(filter);
325
    }
326

    
327
    public void addBaseFilter(String filter) {
328
        try {
329
            this.addBaseFilter(DALLocator.getDataManager().createExpresion(filter));
330
        } catch (InitializeException ex) {
331
            throw new RuntimeException("Can't create filter with '" + filter + "'", ex);
332
        }
333
    }
334

    
335
    /**
336
     * Draws using IFeatureIterator. This method will replace the old draw(...)
337
     * one.
338
     *
339
     * @autor jaume dominguez faus - jaume.dominguez@iver.es
340
     * @param image
341
     * @param g
342
     * @param viewPort
343
     * @param cancel
344
     * @param scale
345
     * @throws ReadDriverException
346
     */
347
    public void draw(BufferedImage image,
348
            Graphics2D g,
349
            ViewPort viewPort,
350
            Cancellable cancel,
351
            double scale) throws ReadException {
352

    
353
        if (legend == null) {
354
            return;
355
        }
356

    
357
        if (!this.isWithinScale(scale)) {
358
            return;
359
        }
360
        if (cancel.isCanceled()) {
361
            return;
362
        }
363

    
364
        if (spatialCache.isEnabled()) {
365
            spatialCache.removeAll();
366
            legend.addDrawingObserver(this);
367
        }
368

    
369
        FeatureQuery featureQuery = createFeatureQuery();
370

    
371
        try {
372
            FeatureAttributeDescriptor featureAttributeDescriptor
373
                    = getFeatureStore().getDefaultFeatureType().getDefaultTimeAttribute();
374

    
375
            if ((viewPort.getTime() != null) && (featureAttributeDescriptor != null)) {
376
                IntersectsTimeEvaluator intersectsTimeEvaluator
377
                        = new IntersectsTimeEvaluator(viewPort.getTime(), featureAttributeDescriptor.getName());
378
                featureQuery.addFilter(intersectsTimeEvaluator);
379
            }
380
        } catch (DataException e1) {
381
            logger.error("Impossible to get the temporal filter", e1);
382
        }
383

    
384
        try {
385

    
386
            long tini = System.currentTimeMillis();
387

    
388
            legend.draw(image,
389
                    g,
390
                    viewPort,
391
                    cancel,
392
                    scale,
393
                    null,
394
                    getCoordTrans(),
395
                    getFeatureStore(),
396
                    featureQuery);
397

    
398
            logger.debug("Layer " + this.getName() + " drawn in "
399
                    + (System.currentTimeMillis() - tini) + " ms ("+this.getFeatureStore().getFullName()+").");
400

    
401
        } catch (LegendException e) {
402
            this.setAvailable(false);
403
            this.setError(e);
404
            throw new ReadException(getName(), e);
405
        } finally {
406
            if (spatialCache.isEnabled()) {
407
                legend.deleteDrawingObserver(this);
408
            }
409
        }
410
    }
411

    
412
    public void print(Graphics2D g,
413
            ViewPort viewPort,
414
            Cancellable cancel,
415
            double scale,
416
            PrintAttributes properties) throws ReadException {
417
        if (!this.isWithinScale(scale)) {
418
            return;
419
        }
420
        if (cancel.isCanceled()) {
421
            return;
422
        }
423
        FeatureQuery featureQuery = createFeatureQuery();
424

    
425
        try {
426
            legend.print(g,
427
                    viewPort,
428
                    cancel,
429
                    scale,
430
                    null,
431
                    getCoordTrans(),
432
                    getFeatureStore(),
433
                    featureQuery,
434
                    properties);
435

    
436
        } catch (LegendException e) {
437
            this.setVisible(false);
438
            this.setActive(false);
439
            throw new ReadException(getName(), e);
440
        }
441
    }
442

    
443
    public void setLegend(IVectorLegend legend) throws LegendLayerException {
444
        if (this.legend == legend) {
445
            return;
446
        }
447
        if (this.legend != null && this.legend.equals(legend)) {
448
            return;
449
        }
450
        IVectorLegend oldLegend = this.legend;
451
        this.legend = legend;
452
        if (oldLegend != null) {
453
            oldLegend.removeLegendListener(this);
454
            oldLegend.deleteDrawingObserver(this);
455
        }
456
        if (legend != null) {
457
            this.legend.addDrawingObserver(this);
458
            this.legend.addLegendListener(this);
459
        }
460
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(oldLegend, this.legend);
461
        e.setLayer(this);
462
        updateDrawVersion();
463
        callLegendChanged(e);
464
    }
465

    
466
    /**
467
     * Devuelve la Leyenda de la capa.
468
     *
469
     * @return Leyenda.
470
     */
471
    public ILegend getLegend() {
472
        return legend;
473
    }
474

    
475
    public int getShapeType() throws ReadException {
476
        if (typeShape == -1) {
477
            FeatureType featureType = null;
478
            try {
479
                if (getDataStore() != null) {
480
                    featureType
481
                            = (((FeatureStore) getDataStore()).getDefaultFeatureType());
482
                }
483
            } catch (DataException e) {
484
                throw new ReadException(getName(), e);
485
            }
486
            if (featureType != null) {
487
                int indexGeom = featureType.getDefaultGeometryAttributeIndex();
488
                typeShape
489
                        = featureType.getAttributeDescriptor(indexGeom).getGeometryType();
490
            }
491
        }
492
        return typeShape;
493
    }
494

    
495
    /**
496
     * Returns the layer's geometry type
497
     *
498
     * @return the geometry type
499
     *
500
     * @throws ReadException if there is an error getting the geometry type
501
     */
502
    public GeometryType getGeometryType() throws ReadException {
503
        FeatureType featureType = null;
504
        try {
505
            if (getDataStore() != null) {
506
                featureType
507
                        = (((FeatureStore) getDataStore()).getDefaultFeatureType());
508
            }
509
        } catch (DataException e) {
510
            throw new ReadException(getName(), e);
511
        }
512
        return featureType == null ? null : featureType
513
                .getDefaultGeometryAttribute().getGeomType();
514
    }
515

    
516
    public void saveToState(PersistentState state) throws PersistenceException {
517

    
518
        FeatureStore featureStore = null;
519

    
520
        if (!this.isAvailable()) {
521
            logger.info("The '" + this.getName() + "' layer is not available, it will persist not.");
522
            return;
523
        }
524

    
525
        try {
526
            super.saveToState(state);
527

    
528
            if (getLegend() != null) {
529
                state.set("legend", getLegend());
530
            }
531

    
532
            featureStore = getFeatureStore();
533

    
534
            if (featureStore != null) {
535
                state.set("featureStore", featureStore);
536
            }
537
            if( this.dataStoreParameters!=null ) {
538
                state.set("featureStoreParameters", dataStoreParameters);
539
            }
540

    
541
            state.set("isLabeled", isLabeled);
542

    
543
            if (strategy != null) {
544
                state.set("labelingStrategy", strategy);
545
            }
546

    
547
            if (getLinkProperties() != null) {
548
                state.set("linkProperties", getLinkProperties());
549
            }
550

    
551
            state.set("typeShape", typeShape);
552
        } catch (PersistenceException ex) {
553
            logger.warn("Can't persist to state the layer '" + this.getName() + "'.", ex);
554
            throw ex;
555
        } catch (RuntimeException ex) {
556
            logger.warn("Can't persist to state the layer '" + this.getName() + "'.", ex);
557
            throw ex;
558
        }
559

    
560
    }
561

    
562
    @Override
563
    public void loadFromState(PersistentState state) throws PersistenceException {
564

    
565
        FeatureStore store = null;
566
        try {
567
            super.loadFromState(state);
568

    
569
            this.setIsLabeled(false);
570
            this.setLabelingStrategy(null);
571

    
572
            typeShape = state.getInt("typeShape", Geometry.TYPES.GEOMETRY);
573

    
574
            this.dataStoreParameters = (DataStoreParameters) state.get("featureStoreParameters");
575

    
576
            store = (FeatureStore) state.get("featureStore");
577
            if (store == null) { 
578
                if( this.dataStoreParameters == null ) {
579
                    this.setAvailable(false);
580
                    this.addError(new RuntimeException("Can't retrieve store information."));
581
                } else {
582
                    if( this.isVisible() ) {
583
                        try {
584
                            DataManager dataManager = DALLocator.getDataManager();
585
                            store = (FeatureStore) dataManager.openStore(
586
                                    this.dataStoreParameters.getProviderName(),
587
                                    this.dataStoreParameters
588
                            );
589
                            this.bindToDataStore(store);
590
                        } catch (Exception ex) {
591
                            this.setAvailable(false);
592
                            this.addError(ex);
593
                        }
594
                    }
595
                }
596
            } else {
597
                if (store.isBroken()) {
598
                    this.setAvailable(false);
599
                    this.addError(store.getBreakingsCause());
600
                }
601
                try {
602
                    this.bindToDataStore(store);
603
                } catch (Exception ex) {
604
                    this.setAvailable(false);
605
                    this.addError(ex);
606
                }
607
            }
608

    
609
            try {
610
                IVectorLegend vectorLegend = (IVectorLegend) state.get("legend");
611
                if( vectorLegend!=null ) {
612
                    this.setLegend(vectorLegend);
613
                }
614
            } catch (Exception ex) {
615
                this.setAvailable(false);
616
                this.addError(ex);
617
            }
618

    
619
            try {
620
                if (state.getBoolean("isLabeled", false)) {
621
                    this.setIsLabeled(true);
622
                    ILabelingStrategy labelingStrategy = (ILabelingStrategy) state.get("labelingStrategy");
623
                    this.setLabelingStrategy(labelingStrategy);
624
                }
625
            } catch (Exception ex) {
626
                this.setAvailable(false);
627
                this.addError(ex);
628
            }
629
            MapContext mc = this.getMapContext();
630
            if(mc != null){
631
                mc.addSelectionListener(this);
632
            }
633

    
634
        } catch (Throwable e) {
635
            String storeName = (store == null) ? "unknow" : store.getFullName();
636
            logger.warn("can't load layer '" + this.getName() + "' (store=" + storeName + ") from persisted state.", e);
637
            this.setAvailable(false);
638
            this.addError(e);
639
        }
640

    
641
    }
642

    
643
    /**
644
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
645
     * identifiquen la capa.
646
     *
647
     * @return DOCUMENT ME!
648
     */
649
    public String toString() {
650
        /*
651
         * Se usa internamente para que la parte de datos identifique de forma
652
         * un?voca las tablas
653
         */
654
        String ret = super.toString();
655

    
656
        return ret; //"layer" + ret.substring(ret.indexOf('@') + 1);
657
    }
658

    
659
    public boolean isEditing() {
660
        FeatureStore fs = getFeatureStore();
661
        if (fs == null) {
662
            /*
663
             * This happens when layer is not available, for example,
664
             * it was not possible to load from persistence
665
             */
666
            return false;
667
        } else {
668
            return fs.isEditing();
669
        }
670
    }
671

    
672
    public void setEditing(boolean b) throws StartEditionLayerException {
673

    
674
        try {
675
            throw new RuntimeException();
676
        } catch (Throwable th) {
677
            logger.info("This method is deprecated. ", th);
678
        }
679

    
680
        if (b == super.isEditing()) {
681
            return;
682
        }
683

    
684
        super.setEditing(b);
685
        FeatureStore fs = getFeatureStore();
686
        if (b) {
687
            try {
688
                fs.edit();
689
            } catch (DataException e) {
690
                throw new StartEditionLayerException(getName(), e);
691
            }
692
        }
693
        getSpatialCache().setEnabled("editing", b);
694
        callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
695
    }
696

    
697
    /**
698
     * @deprecated Use {@link #getSpatialCache()}
699
     */
700
    public void clearSpatialCache() {
701
        spatialCache.removeAll();
702
    }
703

    
704
    /**
705
     * @deprecated Use {@link #getSpatialCache()}
706
     */
707
    public boolean isSpatialCacheEnabled() {
708
        return spatialCache.isEnabled();
709
    }
710

    
711
    /**
712
     * @deprecated Use {@link #getSpatialCache()}
713
     */
714
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
715
        spatialCache.setEnabled(spatialCacheEnabled);
716
    }
717

    
718
    public SpatialCache getSpatialCache() {
719
        return spatialCache;
720
    }
721
    
722
    public void refreshSpatialCache(Envelope envelope) {
723
        if( this.featureStore==null) {
724
            return;
725
        }
726
        SpatialCache sc = this.getSpatialCache();
727
        sc.refresh(this.getName(), this.getFeatureStore(), envelope, this.getProjection());
728
    }
729

    
730
    /**
731
     * Siempre es un numero mayor de 1000
732
     *
733
     * @param maxFeatures
734
     */
735
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
736
        if (maxFeatures > spatialCache.getMaxFeatures()) {
737
            spatialCache.setMaxFeatures(maxFeatures);
738
        }
739

    
740
    }
741

    
742
    /**
743
     * This method returns a boolean that is used by the FPopMenu to make
744
     * visible the properties menu or not. It is visible by default, and if a
745
     * later don't have to show this menu only has to override this method.
746
     *
747
     * @return If the properties menu is visible (or not)
748
     */
749
    public boolean isPropertiesMenuVisible() {
750
        return true;
751
    }
752

    
753
    public void reload() throws ReloadLayerException {
754
        super.reload();
755
        try {
756
            getFeatureStore().refresh();
757
        } catch (Exception e) {
758
            throw new ReloadLayerException(getName(), e);
759
        }
760
    }
761

    
762
    protected void setLoadSelection(Object xml) {
763
        // this.loadSelection = xml;
764
    }
765

    
766
    protected void setLoadLegend(IVectorLegend legend) {
767
        this.loadLegend = legend;
768
    }
769

    
770
    protected void putLoadSelection() {
771
        // if (this.loadSelection == null) return;
772
        // try {
773
        // this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
774
        // } catch (ReadDriverException e) {
775
        // throw new XMLException(e);
776
        // }
777
        // this.loadSelection = null;
778

    
779
    }
780

    
781
    protected void putLoadLegend() throws LegendLayerException {
782
        if (this.loadLegend == null) {
783
            return;
784
        }
785
        this.setLegend(this.loadLegend);
786
        this.loadLegend = null;
787
    }
788

    
789
    protected void cleanLoadOptions() {
790
        this.loadLegend = null;
791
    }
792

    
793
    public boolean isWritable() {
794
        return getFeatureStore().allowWrite();
795
    }
796

    
797
    public FLayer cloneLayer() throws Exception {
798
        FLyrVect clonedLayer = new FLyrVect();
799
        if( this.dataStoreParameters!=null ) {
800
            clonedLayer.dataStoreParameters = (DataStoreParameters) this.dataStoreParameters.getCopy();
801
        }
802
        if( this.featureStore!=null ) {
803
            clonedLayer.featureStore = this.featureStore;
804
            ToolsLocator.getDisposableManager().bind(clonedLayer.featureStore);
805
            clonedLayer.delegate(clonedLayer.featureStore);
806
            clonedLayer.featureStore.addObserver(clonedLayer);
807
        }
808
        clonedLayer.setVisible(isVisible());
809
        clonedLayer.setName(getName());
810
        clonedLayer.setCoordTrans(getCoordTrans());
811

    
812
        if( this.getLegend()!=null ) {
813
            clonedLayer.setLegend((IVectorLegend) getLegend().cloneLegend());
814
        }
815

    
816
        clonedLayer.setIsLabeled(isLabeled());
817
        ILabelingStrategy labelingStrategy = getLabelingStrategy();
818
        if (labelingStrategy != null) {
819
            clonedLayer.setLabelingStrategy(labelingStrategy);
820
        }
821

    
822
        clonedLayer.setMaxScale(this.getMaxScale());
823
        clonedLayer.setMinScale(this.getMinScale());
824
        return clonedLayer;
825
    }
826

    
827
    protected boolean isOnePoint(AffineTransform graphicsTransform,
828
            ViewPort viewPort,
829
            double dpi,
830
            CartographicSupport csSym,
831
            Geometry geom,
832
            int[] xyCoords) {
833
        return isOnePoint(graphicsTransform, viewPort, geom, xyCoords)
834
                && csSym.getCartographicSize(viewPort, dpi, geom) <= 1;
835
    }
836

    
837
    private boolean isOnePoint(AffineTransform graphicsTransform,
838
            ViewPort viewPort,
839
            Geometry geom,
840
            int[] xyCoords) {
841
        boolean onePoint = false;
842
        int type = geom.getType();
843
        if (type == Geometry.TYPES.NULL) {
844
            return false;
845
        }
846
        if (type != Geometry.TYPES.POINT && type != Geometry.TYPES.MULTIPOINT) {
847

    
848
            Envelope geomBounds = geom.getEnvelope();
849

    
850
            // ICoordTrans ct = getCoordTrans();
851
            // Se supone que la geometria ya esta reproyectada
852
            // if (ct!=null) {
853
            // // geomBounds = ct.getInverted().convert(geomBounds);
854
            // geomBounds = geomBounds.convert(ct);
855
            // }
856
            double dist1Pixel = viewPort.getDist1pixel();
857

    
858
            onePoint
859
                    = (geomBounds.getLength(0) <= dist1Pixel && geomBounds.getLength(1) <= dist1Pixel);
860

    
861
            if (onePoint) {
862
                // avoid out of range exceptions
863
                org.gvsig.fmap.geom.primitive.Point p;
864
                try {
865
                    p
866
                            = geomManager.createPoint(geomBounds.getMinimum(0),
867
                                    geomBounds.getMinimum(1),
868
                                    SUBTYPES.GEOM2D);
869
                    p.transform(viewPort.getAffineTransform());
870
                    p.transform(graphicsTransform);
871
                    xyCoords[0] = (int) p.getX();
872
                    xyCoords[1] = (int) p.getY();
873
                } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
874
                    logger.error("Error creating a point", e);
875
                }
876

    
877
            }
878

    
879
        }
880
        return onePoint;
881
    }
882

    
883
    public boolean isLabeled() {
884
        return isLabeled;
885
    }
886

    
887
    public void setIsLabeled(boolean isLabeled) {
888
        this.isLabeled = isLabeled;
889
    }
890

    
891
    public ILabelingStrategy getLabelingStrategy() {
892
        return strategy;
893
    }
894

    
895
    public void setLabelingStrategy(ILabelingStrategy strategy) {
896
        this.strategy = strategy;
897
        if (strategy == null) {
898
            return;
899
        }
900
        strategy.setLayer(this);
901
        updateDrawVersion();
902
    }
903

    
904
    public void drawLabels(BufferedImage image,
905
            Graphics2D g,
906
            ViewPort viewPort,
907
            Cancellable cancel,
908
            double scale,
909
            double dpi) throws ReadException {
910
        if (strategy != null && isWithinScale(scale)) {
911
            strategy.draw(image, g, scale, viewPort, cancel, dpi);
912
        }
913
    }
914

    
915
    public void printLabels(Graphics2D g,
916
            ViewPort viewPort,
917
            Cancellable cancel,
918
            double scale,
919
            PrintAttributes properties) throws ReadException {
920
        if (strategy != null) {
921
            strategy.print(g, scale, viewPort, cancel, properties);
922
        }
923
    }
924

    
925
    /**
926
     * Return true, because a Vectorial Layer supports HyperLink
927
     *
928
     * @deprecated the hiperlink functionaliti is out the layer now
929
     */
930
    public boolean allowLinks() {
931
        return false;
932
    }
933

    
934
    public void load() throws LoadLayerException {
935
        super.load();
936
    }
937

    
938
    public FeatureStore getFeatureStore() {
939
        return (FeatureStore) getDataStore();
940
    }
941

    
942
    public FeatureQuery createFeatureQuery() {
943
        if (this.baseQuery == null) {
944
            return this.getFeatureStore().createFeatureQuery();
945
        }
946
        try {
947
            return (FeatureQuery) baseQuery.clone();
948
        } catch (CloneNotSupportedException ex) {
949
            throw new RuntimeException(ex);
950
        }
951
    }
952

    
953
    /**
954
     * @deprecated use instead
955
     * {@link #queryByPoint(org.gvsig.fmap.geom.primitive.Point, double, FeatureType)}
956
     */
957
    public FeatureSet queryByPoint(Point2D mapPoint,
958
            double tol,
959
            FeatureType featureType) throws DataException {
960
        logger.warn("Deprecated use of queryByPoint.");
961
        GeometryManager manager = GeometryLocator.getGeometryManager();
962
        org.gvsig.fmap.geom.primitive.Point center;
963
        try {
964
            center
965
                    = (org.gvsig.fmap.geom.primitive.Point) manager.create(TYPES.POINT,
966
                            SUBTYPES.GEOM2D);
967
            center.setX(mapPoint.getX());
968
            center.setY(mapPoint.getY());
969
            Circle circle
970
                    = (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
971
            circle.setPoints(center, tol);
972
            return queryByGeometry(circle, featureType);
973
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
974
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
975
        }
976
    }
977

    
978
    public FeatureSet queryByPoint(org.gvsig.fmap.geom.primitive.Point point,
979
            double tol,
980
            FeatureType featureType) throws DataException {
981
        GeometryManager manager = GeometryLocator.getGeometryManager();
982
        try {
983
            Circle circle
984
                    = (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
985
            circle.setPoints(point, tol);
986
            return queryByGeometry(circle, featureType);
987
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
988
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
989
        }
990
    }
991

    
992
    public FeatureQuery createQueryByPoint(double x, double y,
993
            double tol,
994
            FeatureType featureType) throws DataException {
995
        GeometryManager manager = GeometryLocator.getGeometryManager();
996
        org.gvsig.fmap.geom.primitive.Point center;
997
        try {
998
            center
999
                    = (org.gvsig.fmap.geom.primitive.Point) manager.create(TYPES.POINT,
1000
                            SUBTYPES.GEOM2D);
1001
            center.setX(x);
1002
            center.setY(y);
1003
            Circle circle
1004
                    = (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
1005
            circle.setPoints(center, tol);
1006
            return createQueryByGeometry(circle, featureType);
1007
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
1008
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
1009
        }
1010
    }
1011

    
1012
    /**
1013
     * Input geom must be in the CRS of the view.
1014
     *
1015
     * @param geom
1016
     * @param featureType
1017
     * @return
1018
     * @throws DataException
1019
     */
1020
    public FeatureSet queryByGeometry(Geometry geom, FeatureType featureType) throws DataException {
1021
        FeatureQuery featureQuery = createFeatureQuery();
1022
        featureQuery.setFeatureType(featureType);
1023

    
1024
        Geometry query_geo = this.transformToSourceCRS(geom, true);
1025
        IProjection query_proj = getMapContext().getProjection();
1026
        if (this.getCoordTrans() != null) {
1027
            query_proj = this.getCoordTrans().getPOrig();
1028
        }
1029
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().intersects(
1030
                query_geo,
1031
                query_proj,
1032
                featureStore
1033
        );
1034
        featureQuery.setFilter(iee);
1035
        featureQuery.setAttributeNames(null);
1036
        return getFeatureStore().getFeatureSet(featureQuery);
1037

    
1038
    }
1039
    
1040
    public FeatureQuery createQueryByGeometry(Geometry geom, FeatureType featureType) throws DataException {
1041
        FeatureQuery featureQuery = createFeatureQuery();
1042
        featureQuery.setFeatureType(featureType);
1043

    
1044
        Geometry query_geo = this.transformToSourceCRS(geom, true);
1045
        IProjection query_proj = getMapContext().getProjection();
1046
        if (this.getCoordTrans() != null) {
1047
            query_proj = this.getCoordTrans().getPOrig();
1048
        }
1049
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().intersects(
1050
                query_geo,
1051
                query_proj,
1052
                featureStore
1053
        );
1054
        featureQuery.setFilter(iee);
1055
        featureQuery.setAttributeNames(null);
1056
        return featureQuery;
1057

    
1058
    }
1059
    
1060
    public FeatureSet queryByContainedInGeometry(Geometry geom, FeatureType featureType) throws DataException {
1061
        FeatureQuery featureQuery = createFeatureQuery();
1062
        featureQuery.setFeatureType(featureType);
1063

    
1064
        Geometry query_geo = this.transformToSourceCRS(geom, true);
1065
        IProjection query_proj = getMapContext().getProjection();
1066
        if (this.getCoordTrans() != null) {
1067
            query_proj = this.getCoordTrans().getPOrig();
1068
        }
1069
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().contains(
1070
                query_geo,
1071
                query_proj,
1072
                featureStore
1073
        );
1074
        featureQuery.setFilter(iee);
1075
        featureQuery.setAttributeNames(null);
1076
        return getFeatureStore().getFeatureSet(featureQuery);
1077

    
1078
    }
1079
    /**
1080
     * It return the {@link FeatureSet} that intersects with the envelope.
1081
     *
1082
     * @param envelope envelope that defines the area for the query.
1083
     * @param featureType only the features with this feature type are used in
1084
     * the query.
1085
     * @return the set of features that intersect with the envelope.
1086
     * @throws DataException
1087
     */
1088
    public FeatureSet queryByEnvelope(Envelope envelope, FeatureType featureType) throws DataException {
1089
        return queryByEnvelope(envelope, featureType, null);
1090
    }
1091

    
1092
    /**
1093
     * It return the {@link FeatureSet} that intersects with the envelope.
1094
     *
1095
     * @param envelope envelope that defines the area for the query in viewport
1096
     * CRS
1097
     * @param featureType only the features with this feature type are used in
1098
     * the query.
1099
     * @param names the feature attributes that have to be checked.
1100
     * @return the set of features that intersect with the envelope.
1101
     * @throws DataException
1102
     */
1103
    public FeatureSet queryByEnvelope(Envelope envelope,
1104
            FeatureType featureType,
1105
            String[] names) throws DataException {
1106
        FeatureQuery featureQuery = createFeatureQuery();
1107
        if (names == null) {
1108
            featureQuery.setFeatureType(featureType);
1109
        } else {
1110
            featureQuery.setAttributeNames(names);
1111
            featureQuery.setFeatureTypeId(featureType.getId());
1112
        }
1113

    
1114
        Envelope query_env = fromViewPortCRSToSourceCRS(this, envelope);
1115
        IProjection query_proj = getMapContext().getProjection();
1116
        if (this.getCoordTrans() != null) {
1117
            query_proj = this.getCoordTrans().getPOrig();
1118
        }
1119

    
1120
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().intersects(
1121
                query_env.getGeometry(),
1122
                query_proj,
1123
                featureStore
1124
        );
1125
        featureQuery.setFilter(iee);
1126
        return getFeatureStore().getFeatureSet(featureQuery);
1127

    
1128
    }
1129
    
1130
    public FeatureSet queryByContainedInEnvelope(Envelope envelope, FeatureType featureType) throws DataException {
1131
        return queryByContainedInEnvelope(envelope, featureType, null);
1132
    }
1133
    
1134
    public FeatureSet queryByContainedInEnvelope(Envelope envelope,
1135
            FeatureType featureType,
1136
            String[] names) throws DataException {
1137
        FeatureQuery featureQuery = createFeatureQuery();
1138
        if (names == null) {
1139
            featureQuery.setFeatureType(featureType);
1140
        } else {
1141
            featureQuery.setAttributeNames(names);
1142
            featureQuery.setFeatureTypeId(featureType.getId());
1143
        }
1144

    
1145
        Envelope query_env = fromViewPortCRSToSourceCRS(this, envelope);
1146
        IProjection query_proj = getMapContext().getProjection();
1147
        if (this.getCoordTrans() != null) {
1148
            query_proj = this.getCoordTrans().getPOrig();
1149
        }
1150

    
1151
        Evaluator iee = SpatialEvaluatorsFactory.getInstance().contains(
1152
                query_env.getGeometry(),
1153
                query_proj,
1154
                featureStore
1155
        );
1156
        featureQuery.setFilter(iee);
1157
        return getFeatureStore().getFeatureSet(featureQuery);
1158

    
1159
    }
1160
    
1161
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel) throws LoadLayerException,
1162
            DataException {
1163

    
1164
        return getInfo(p, tolerance, cancel, true);
1165
    }
1166

    
1167
    public DynObjectSet getInfo(Point p,
1168
            double tolerance,
1169
            Cancellable cancel,
1170
            boolean fast) throws LoadLayerException, DataException {
1171
        Point2D infop = new Point2D.Double(p.x, p.y);
1172
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(infop);
1173
        return queryByPoint(pReal,
1174
                tolerance,
1175
                getFeatureStore().getDefaultFeatureType()).getDynObjectSet(fast);
1176
    }
1177

    
1178
    public DynObjectSet getInfo(org.gvsig.fmap.geom.primitive.Point p,
1179
            double tolerance) throws LoadLayerException, DataException {
1180
        return queryByPoint(p, tolerance, getFeatureStore().getDefaultFeatureType()).getDynObjectSet(false);
1181
    }
1182

    
1183
    @Override
1184
    public void legendCleared(LegendClearEvent event) {
1185
        this.updateDrawVersion();
1186
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(legend, event);
1187
        this.callLegendChanged(e);
1188
    }
1189

    
1190
    @Override
1191
    public boolean symbolChanged(SymbolLegendEvent e) {
1192
        this.updateDrawVersion();
1193
        LegendChangedEvent ev = LegendChangedEvent.createLegendChangedEvent(legend, e);
1194
        this.callLegendChanged(ev);
1195
        return true;
1196
    }
1197

    
1198
    public void update(Observable observable, Object notification) {
1199
        if (observable.equals(this.featureStore)) {
1200
            if (notification instanceof FeatureStoreNotification) {
1201
                FeatureStoreNotification event
1202
                        = (FeatureStoreNotification) notification;
1203
                if (event.getType() == FeatureStoreNotification.AFTER_DELETE
1204
                        || event.getType() == FeatureStoreNotification.AFTER_UNDO
1205
                        || event.getType() == FeatureStoreNotification.AFTER_REDO
1206
                        || event.getType() == FeatureStoreNotification.AFTER_REFRESH
1207
                        || event.getType() == FeatureStoreNotification.AFTER_UPDATE
1208
                        || event.getType() == FeatureStoreNotification.AFTER_UPDATE_TYPE
1209
//                        || event.getType() == FeatureStoreNotification.SELECTION_CHANGE
1210
                        || event.getType() == FeatureStoreNotification.AFTER_INSERT) {
1211
                    this.updateDrawVersion();
1212

    
1213
                } else if (event.getType() == FeatureStoreNotification.AFTER_CANCELEDITING) {
1214
                    getSpatialCache().setEnabled("editing", false);
1215

    
1216
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1217
                    this.updateDrawVersion();
1218

    
1219
                } else if (event.getType() == FeatureStoreNotification.AFTER_STARTEDITING) {
1220
                    getSpatialCache().setEnabled("editing", true);
1221
                    
1222
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1223

    
1224
                } else if (event.getType() == FeatureStoreNotification.TRANSFORM_CHANGE) {
1225
                    //If a transform has to be applied, try to reload the layer.
1226
                    try {
1227
                        reload();
1228
                    } catch (ReloadLayerException e) {
1229
                        logger.info("While reloading layer.", e);
1230
                        this.setAvailable(false);
1231
                    }
1232
                } else if (event.getType() == FeatureStoreNotification.RESOURCE_CHANGED) {
1233
                    this.setAvailable(false);
1234
                } else if (event.getType() == FeatureStoreNotification.AFTER_FINISHEDITING) {
1235
                    this.setAvailable(true);
1236
                    getSpatialCache().setEnabled("editing", false);
1237
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
1238
                    this.updateDrawVersion();
1239
                } else if (event.getType() == FeatureStoreNotification.SELECTION_CHANGE) {
1240
                    callSelectionChanged();
1241
                }
1242
            }
1243
        } else if (notification instanceof FeatureDrawnNotification
1244
                && spatialCache.isEnabled()) {
1245
            // This code is needed in editing mode
1246
            // for all layers involved in snapping
1247
            // (including the layer being edited)            
1248
            Geometry geometry
1249
                    = ((FeatureDrawnNotification) notification).getDrawnGeometry();
1250
            spatialCache.insert(geometry.getEnvelope(), geometry);
1251
        }
1252
    }
1253

    
1254
    public void setLayerToSnap(boolean enable) {
1255
        MapContext mapContext = this.getMapContext();
1256
        Set<FLyrVect> layers = (Set<FLyrVect>) mapContext.getLayersToSnap();
1257
        if( enable ) {
1258
            layers.add(this);
1259
        } else {
1260
            layers.remove(this);
1261
        }
1262
        mapContext.setLayersToSnap(layers);
1263
        this.getSpatialCache().setEnabled(enable);
1264
    }
1265
    
1266
    public boolean isLayerToSnap() {
1267
        MapContext mapContext = this.getMapContext();
1268
        if ( mapContext == null) {
1269
            return false;
1270
        }
1271
        return mapContext.getLayersToSnap().contains(this);
1272
    }
1273

    
1274
    /*
1275
     * (non-Javadoc)
1276
     *
1277
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1278
     */
1279
    public Set getMetadataChildren() {
1280
        Set ret = new TreeSet();
1281
        ret.add(this.featureStore);
1282
        return ret;
1283
    }
1284

    
1285
    /*
1286
     * (non-Javadoc)
1287
     *
1288
     * @see org.gvsig.metadata.Metadata#getMetadataID()
1289
     */
1290
    public Object getMetadataID() throws MetadataException {
1291
        return "Layer(" + this.getName() + "):"
1292
                + this.featureStore.getMetadataID();
1293
    }
1294

    
1295
    public GeometryType getTypeVectorLayer() throws DataException,
1296
            LocatorException,
1297
            GeometryTypeNotSupportedException,
1298
            GeometryTypeNotValidException {
1299
        // Este metodo esta duplicado ?? getShapeType()
1300
        FeatureStore fs = this.getFeatureStore();
1301
        FeatureType fType = fs.getDefaultFeatureType();
1302
        FeatureAttributeDescriptor attr
1303
                = fType.getAttributeDescriptor(fType.getDefaultGeometryAttributeIndex());
1304
        GeometryType geomType = attr.getGeomType();
1305
        return geomType;
1306
    }
1307

    
1308
    public static class SelfRegister
1309
            implements Callable {
1310

    
1311
        @Override
1312
        public Object call() {
1313
          registerPersistence();
1314
          registerDefaultVectorLayer();
1315
          DynObjectManager dynObjectManager = ToolsLocator.getDynObjectManager();
1316
          dynObjectManager.registerTag(TAG_LAYERVECT_MAXSCALE, "Sets the maximum scale visible. Higher scales won't be drawn, -1 if not defined");
1317
          dynObjectManager.registerTag(TAG_LAYERVECT_MINSCALE, "Sets the minimum scale visible. Lower scales won't be drawn, -1 if not defined");
1318
          return true;
1319
        }
1320
        
1321
        private Object registerDefaultVectorLayer() {
1322
            MapContextManager manager = MapContextLocator.getMapContextManager();
1323
            manager.registerLayer(FeatureStore.class, FLyrVect.class);
1324
            return true;          
1325
        }
1326
        
1327
        private Object registerPersistence() {
1328
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
1329

    
1330
            DynStruct definition
1331
                    = manager.addDefinition(FLyrVect.class,
1332
                            "FLyrVect",
1333
                            "FLyrVect Persistence definition",
1334
                            null,
1335
                            null);
1336
            definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE,
1337
                    "FLyrDefault");
1338

    
1339
            definition.addDynFieldObject("legend")
1340
                    .setClassOfValue(IVectorLegend.class)
1341
                    .setMandatory(false);
1342
            definition.addDynFieldObject("featureStore")
1343
                    .setClassOfValue(FeatureStore.class)
1344
                    .setMandatory(false);
1345
            definition.addDynFieldBoolean("isLabeled").setMandatory(true);
1346
            definition.addDynFieldInt("typeShape").setMandatory(true);
1347
            definition.addDynFieldObject("labelingStrategy")
1348
                    .setClassOfValue(ILabelingStrategy.class)
1349
                    .setMandatory(false);
1350
            definition.addDynFieldObject("featureStoreParameters")
1351
                    .setClassOfValue(OpenFeatureStoreParameters.class)
1352
                    .setMandatory(false);
1353

    
1354
            return true;
1355
        }
1356
    }
1357

    
1358
    @Override
1359
    protected void doDispose() throws BaseException {
1360
        dispose(featureStore);
1361
        spatialCache.removeAll();
1362
    }
1363

    
1364
    /**
1365
     * Returns envelope in layer's data source CRS from envelope provided in
1366
     * viewport CRS
1367
     *
1368
     * @param lyr
1369
     * @param env
1370
     * @return
1371
     */
1372
    public static Envelope fromViewPortCRSToSourceCRS(FLayer lyr, Envelope env) {
1373

    
1374
        if (lyr == null || env == null) {
1375
            return null;
1376
        }
1377

    
1378
        ICoordTrans ct = lyr.getCoordTrans();
1379
        if (ct == null) {
1380
            return env;
1381
        } else {
1382
            return env.convert(ct.getInverted());
1383
        }
1384
    }
1385

    
1386
    public Geometry transformToSourceCRS(Geometry geom, boolean clone) {
1387
        return fromViewPortCRSToSourceCRS(this, geom, clone);
1388
    }
1389

    
1390
    /**
1391
     * Returns geometry in layer's data source CRS from geometry provided in
1392
     * viewport CRS
1393
     *
1394
     * @param lyr
1395
     * @param geo
1396
     * @param clone
1397
     * @return
1398
     * @deprecated use the transformToSourceCRS method of layer.
1399
     */
1400
    public static Geometry fromViewPortCRSToSourceCRS(
1401
            FLayer lyr,
1402
            Geometry geo,
1403
            boolean clone) {
1404

    
1405
        if (lyr == null || geo == null) {
1406
            return null;
1407
        }
1408
        ICoordTrans ct = lyr.getCoordTrans();
1409
        Geometry resp = geo;
1410
        if (clone) {
1411
            resp = resp.cloneGeometry();
1412
        }
1413
        if (ct != null) {
1414
            resp.reProject(ct.getInverted());
1415
        }
1416
        return resp;
1417
    }
1418

    
1419
    public Iterator iterator() {
1420
        return this.getFeatureStore().iterator();
1421
    }
1422

    
1423
    protected class EnvelopeCantBeInitializedException
1424
            extends BaseException {
1425

    
1426
        /**
1427
         *
1428
         */
1429
        private static final long serialVersionUID = 4572797479347381552L;
1430
        private final static String MESSAGE_FORMAT = "The envelope can't be initialized, maybe the layer has a wrong projection. Change the projection in layer properties of the add layer dialog to try fix it.";
1431
        private final static String MESSAGE_KEY = "_EnvelopeCantBeInitializedException";
1432

    
1433
        public EnvelopeCantBeInitializedException() {
1434
            super(MESSAGE_FORMAT, null, MESSAGE_KEY, serialVersionUID);
1435
        }
1436
    }
1437

    
1438
    @Override
1439
    public String getInfoString() {
1440
        LayerInformationBuilder builder = MapContextLocator.getMapContextManager().createLayerInformationBuilder();
1441

    
1442
        if (!this.isAvailable()) {
1443
            builder.title().labelkey("Warning");
1444
            builder.text().value("The layer is not available.");
1445
        }
1446

    
1447
        Envelope env = null;
1448
        FeatureAttributeDescriptor attrgeom = null;
1449

    
1450
        try {
1451
            env = this.getFullEnvelope();
1452
        } catch (Exception ex) {
1453
        }
1454
        FeatureStore store = this.getFeatureStore();
1455
        try {
1456
            FeatureType ft = store.getDefaultFeatureType();
1457
            attrgeom = ft.getDefaultGeometryAttribute();
1458
        } catch (Exception ex) {
1459
        }
1460

    
1461
        builder.title().labelkey("Data_source");
1462
        builder.property().labelkey("Source_type").value(this.getProviderName());
1463
        builder.property().labelkey("origen").value(store==null? "not available":store.getFullName());
1464
        if (this.getDataStoreParameters() instanceof FilesystemStoreParameters) {
1465
            File f = ((FilesystemStoreParameters) (this.getDataStoreParameters())).getFile();
1466
            if (f != null && f.exists()) {
1467
                builder.property().labelkey("_Size").value("%d bytes", f.length());
1468
            }
1469
        }
1470
        if (attrgeom != null) {
1471
            builder.property().labelkey("_Geometry_column").value(attrgeom.getName());
1472
            builder.property().labelkey("_Geometry_type").value(attrgeom.getGeomType().getFullName());
1473
        }
1474

    
1475
        builder.title().labelkey("_Coordenadas_geograficas");
1476
        if (this.isAvailable()) {
1477
            builder.envelope().value(env);
1478
        }
1479

    
1480
        builder.title().labelkey("_Projection");
1481
        if (this.isAvailable()) {
1482
            builder.property().value(this.getProjection());
1483
            builder.text().asWKT(this.getProjection());
1484
        }
1485
        return builder.toString();
1486
    }
1487

    
1488
    @Override
1489
    public boolean isTemporary() {
1490
        if (this.featureStore != null) {
1491
            if (this.featureStore.isTemporary()) {
1492
                return true;
1493
            }
1494
        }
1495
        return super.isTemporary();
1496
    }
1497
    
1498
    private String getProviderName() {
1499
        if( this.featureStore!=null ) {
1500
            return this.featureStore.getProviderName();
1501
        }
1502
        if( this.dataStoreParameters!=null ) {
1503
            return this.dataStoreParameters.getProviderName();
1504
        }
1505
        return null;
1506
    }
1507
    
1508
    public DataStoreParameters getDataStoreParameters() {
1509
        if( this.featureStore!=null ) {
1510
            return this.featureStore.getParameters();
1511
        }
1512
        if( this.dataStoreParameters!=null ) {
1513
            return this.dataStoreParameters;
1514
        }
1515
        return null;
1516
    }
1517
    
1518
    public IProjection getProjection() {
1519
        if( this.featureStore==null) {
1520
            if(this.dataStoreParameters==null) {
1521
                return null;
1522
            }
1523
            if(!this.isVisible()){
1524
                return null;
1525
            }
1526
            try {
1527
                DataManager dataManager = DALLocator.getDataManager();
1528
                DataStore dataStore = dataManager.openStore(
1529
                        this.dataStoreParameters.getProviderName(),
1530
                        this.dataStoreParameters
1531
                );
1532
                this.bindToDataStore(dataStore);
1533
                IProjection projection = (IProjection) dataStore.getDynValue(FeatureStore.METADATA_CRS);
1534
                if (projection != null) {
1535
                    this.setProjection(projection);
1536
                }
1537
                if (projection != null && this.getMapContext() != null) {
1538
                    IProjection mapContextProj = this.getMapContext().getProjection();
1539
                    if (!projection.getAbrev().equals(mapContextProj.getAbrev())) {
1540
                        ICoordTrans ct = projection.getCT(mapContextProj);
1541
                        this.setCoordTrans(ct);
1542
                    } else {
1543
                        this.setCoordTrans(null);
1544
                    }
1545
                }
1546
            } catch (Exception ex) {
1547
                throw new RuntimeException("Can't set visibility to layer", ex);
1548
            }
1549
        }
1550
        return super.getProjection();
1551
    }
1552
    
1553
    private void callSelectionChanged() {
1554
        this.updateDrawVersion(false);
1555
        SelectionEvent e = new SelectionEvent();
1556
        for (LayerListener listener : this.layerListeners) {
1557
            if( listener instanceof SelectionListener ) {
1558
                SelectionListener l = (SelectionListener) listener;
1559
                try {
1560
                    l.selectionChanged(e);
1561
                } catch (Exception ex) {
1562
                    logger.warn("Error calling listener '" + listener.toString() + "'.", ex);
1563
                }
1564
            }
1565
        }
1566
    }    
1567

    
1568
    @Override
1569
    public void invalidate() {
1570
        this.updateDrawVersion();
1571
    }
1572
    
1573
    @Override
1574
    public Object getProperty(Object key) {
1575
        Object v = properties.getProperty(key);
1576
        if( v == null ) {
1577
            FeatureStore store = this.getFeatureStore();
1578
            if( store!= null ) {
1579
                FeatureType ft = store.getDefaultFeatureTypeQuietly();
1580
                v = ft.getTags().get("Layer."+key);
1581
            }
1582
        }
1583
        return v;
1584
    }
1585

    
1586
}