Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_mapcontext / src / org / gvsig / fmap / mapcontext / layers / vectorial / FLyrVect.java @ 39491

History | View | Annotate | Download (36.2 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package org.gvsig.fmap.mapcontext.layers.vectorial;
42

    
43
import java.awt.Graphics2D;
44
import java.awt.Point;
45
import java.awt.geom.AffineTransform;
46
import java.awt.geom.Point2D;
47
import java.awt.image.BufferedImage;
48
import java.util.Set;
49
import java.util.TreeSet;
50

    
51
import org.cresques.cts.ICoordTrans;
52
import org.slf4j.LoggerFactory;
53

    
54
import org.gvsig.compat.print.PrintAttributes;
55
import org.gvsig.fmap.dal.DataStore;
56
import org.gvsig.fmap.dal.exception.DataException;
57
import org.gvsig.fmap.dal.exception.ReadException;
58
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
59
import org.gvsig.fmap.dal.feature.FeatureQuery;
60
import org.gvsig.fmap.dal.feature.FeatureSet;
61
import org.gvsig.fmap.dal.feature.FeatureStore;
62
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
63
import org.gvsig.fmap.dal.feature.FeatureType;
64
import org.gvsig.fmap.dal.feature.exception.CreateGeometryException;
65
import org.gvsig.fmap.geom.Geometry;
66
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
67
import org.gvsig.fmap.geom.Geometry.TYPES;
68
import org.gvsig.fmap.geom.GeometryLocator;
69
import org.gvsig.fmap.geom.GeometryManager;
70
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
71
import org.gvsig.fmap.geom.primitive.Circle;
72
import org.gvsig.fmap.geom.primitive.Envelope;
73
import org.gvsig.fmap.geom.type.GeometryType;
74
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
75
import org.gvsig.fmap.geom.type.GeometryTypeNotValidException;
76
import org.gvsig.fmap.mapcontext.MapContextLocator;
77
import org.gvsig.fmap.mapcontext.MapContextManager;
78
import org.gvsig.fmap.mapcontext.ViewPort;
79
import org.gvsig.fmap.mapcontext.exceptions.LegendLayerException;
80
import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
81
import org.gvsig.fmap.mapcontext.exceptions.ReloadLayerException;
82
import org.gvsig.fmap.mapcontext.exceptions.StartEditionLayerException;
83
import org.gvsig.fmap.mapcontext.layers.FLayer;
84
import org.gvsig.fmap.mapcontext.layers.FLyrDefault;
85
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
86
import org.gvsig.fmap.mapcontext.layers.SpatialCache;
87
import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
88
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
89
import org.gvsig.fmap.mapcontext.rendering.legend.LegendException;
90
import org.gvsig.fmap.mapcontext.rendering.legend.events.FeatureDrawnNotification;
91
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
92
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendClearEvent;
93
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendContentsChangedListener;
94
import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
95
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelingStrategy;
96
import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport;
97
import org.gvsig.metadata.exceptions.MetadataException;
98
import org.gvsig.tools.ToolsLocator;
99
import org.gvsig.tools.dynobject.DynObjectSet;
100
import org.gvsig.tools.dynobject.DynStruct;
101
import org.gvsig.tools.exception.BaseException;
102
import org.gvsig.tools.locator.LocatorException;
103
import org.gvsig.tools.observer.Observable;
104
import org.gvsig.tools.observer.Observer;
105
import org.gvsig.tools.persistence.PersistenceManager;
106
import org.gvsig.tools.persistence.PersistentState;
107
import org.gvsig.tools.persistence.exception.PersistenceException;
108
import org.gvsig.tools.persistence.exception.PersistenceRuntimeException;
109
import org.gvsig.tools.task.Cancellable;
110

    
111
/**
112
 * Capa b?sica Vectorial.
113
 * 
114
 */
115

    
116
public class FLyrVect extends FLyrDefault implements VectorLayer,
117
    LegendContentsChangedListener, Observer {
118

    
119
    final static private org.slf4j.Logger logger =
120
        LoggerFactory.getLogger(FLyrVect.class);
121
    private final GeometryManager geomManager =
122
        GeometryLocator.getGeometryManager();
123

    
124
    /** Leyenda de la capa vectorial */
125
    private IVectorLegend legend;
126
    private int typeShape = -1;
127
    private FeatureStore featureStore = null;
128
    private SpatialCache spatialCache = new SpatialCache();
129

    
130
    /**
131
     * An implementation of gvSIG spatial index
132
     */
133
    // protected ISpatialIndex spatialIndex = null;
134
    private IVectorLegend loadLegend = null;
135

    
136
    private boolean isLabeled;
137
    protected ILabelingStrategy strategy;
138
//        private ReprojectDefaultGeometry reprojectTransform;
139

    
140
    public FLyrVect() {
141
        super();
142
    }
143
    
144
        public String getTocImageIcon() {
145
            if (this.isAvailable()) {
146
            return MapContextLocator.getMapContextManager().getIconLayer(this.getDataStore());
147
            } else {
148
                /*
149
                 * data store can be be null,
150
                 * for example, a layer not loaded from persistence
151
                 */
152
            return "layer-icon-unavailable";
153
            }
154
                
155
        }
156

    
157
    /**
158
     * Devuelve el VectorialAdapater de la capa.
159
     * 
160
     * @return VectorialAdapter.
161
     */
162
    public DataStore getDataStore() {
163
        if (!this.isAvailable()) {
164
            return null;
165
        }
166
        return featureStore;
167
    }
168
    
169
    /**
170
     * Asigna el data-store a la capa.
171
     * Esta operacion no se deneria poder hacer desde fuera de la clase.
172
     * 
173
     * @param dataStore
174
     * @throws LoadLayerException
175
     * @deprecated use {@link #bindToDataStore(DataStore)}
176
     */
177
    public void setDataStore(DataStore dataStore) throws LoadLayerException {
178
            bindToDataStore(dataStore);
179
    }
180
    
181
    /**
182
     * Enlaza la capa con el DataStore indicado.
183
     *  
184
     * @param dataStore
185
     * @throws LoadLayerException
186
     */
187
    protected void bindToDataStore(DataStore dataStore) throws LoadLayerException {
188
        if (this.featureStore != null && this.featureStore != dataStore) {
189
            this.featureStore.deleteObserver(this);
190
        }
191

    
192
        featureStore = (FeatureStore) dataStore;
193

    
194
        MapContextManager mapContextManager =
195
            MapContextLocator.getMapContextManager();
196
        
197
        //Set the legend
198
        IVectorLegend legend =
199
            (IVectorLegend)mapContextManager.getLegend(dataStore);
200

    
201
        if (legend == null) {
202
            throw new LegendLayerException(this.getName());
203
        }
204

    
205
        this.setLegend(legend);
206

    
207
        //Set the labeling strategy
208
        ILabelingStrategy labeler = 
209
            (ILabelingStrategy) mapContextManager.getLabelingStrategy(dataStore);
210

    
211
        if (labeler != null) {
212
            labeler.setLayer(this);
213
            this.setLabelingStrategy(labeler);
214
            this.setIsLabeled(true); // TODO: ac? no s'hauria de detectar si t?
215
                                     // etiquetes?????
216
        }
217

    
218
        this.delegate(dataStore);
219

    
220
        dataStore.addObserver(this);
221

    
222
        ToolsLocator.getDisposableManager().bind(dataStore);
223
    }
224

    
225
    public Envelope getFullEnvelope() throws ReadException {
226
        Envelope rAux;
227
        try {
228
            rAux = getFeatureStore().getEnvelope();
229
        } catch (BaseException e) {
230
            throw new ReadException(getName(), e);
231
        }
232

    
233
        // Esto es para cuando se crea una capa nueva con el fullExtent de ancho
234
        // y alto 0.
235
        if (rAux == null || rAux.isEmpty() || rAux.getMaximum(0) - rAux.getMinimum(0) == 0
236
            && rAux.getMaximum(1) - rAux.getMinimum(1) == 0) {
237
            try {
238
                rAux =
239
                    geomManager.createEnvelope(0, 0, 90, 90, SUBTYPES.GEOM2D);
240
            } catch (CreateEnvelopeException e) {
241
                logger.error("Error creating the envelope", e);
242
                e.printStackTrace();
243
            }
244
        }
245
        // Si existe reproyecci?n, reproyectar el extent
246
        ICoordTrans ct = getCoordTrans();
247
        if (ct != null) {
248
                rAux = rAux.convert(ct);
249
        }
250
        return rAux;
251

    
252
    }
253

    
254
    /**
255
     * Draws using IFeatureIterator. This method will replace the old draw(...)
256
     * one.
257
     * 
258
     * @autor jaume dominguez faus - jaume.dominguez@iver.es
259
     * @param image
260
     * @param g
261
     * @param viewPort
262
     * @param cancel
263
     * @param scale
264
     * @throws ReadDriverException
265
     */
266
    public void draw(BufferedImage image,
267
        Graphics2D g,
268
        ViewPort viewPort,
269
        Cancellable cancel,
270
        double scale) throws ReadException {
271

    
272
        if (legend == null) {
273
            return;
274
        }
275

    
276
        if (!this.isWithinScale(scale)) {
277
            return;
278
        }
279
        if (cancel.isCanceled()) {
280
            return;
281
        }
282

    
283
        if (spatialCache.isEnabled()) {
284
            spatialCache.clearAll();
285
            legend.addDrawingObserver(this);
286
        }
287

    
288
        FeatureQuery featureQuery = null;
289
        try {
290
            FeatureAttributeDescriptor featureAttributeDescriptor =
291
                getFeatureStore().getDefaultFeatureType().getDefaultTimeAttribute();
292

    
293
            if ((viewPort.getTime() != null) && (featureAttributeDescriptor != null)){
294
                featureQuery = getFeatureStore().createFeatureQuery();
295
                IntersectsTimeEvaluator intersectsTimeEvaluator =
296
                    new IntersectsTimeEvaluator(viewPort.getTime(), featureAttributeDescriptor.getName());
297
                featureQuery.addFilter(intersectsTimeEvaluator);
298
            }
299
        } catch (DataException e1) {
300
            logger.error("Impossible to get the temporal filter", e1);
301
        }
302

    
303
        try {
304
            
305
            long tini = System.currentTimeMillis();
306
            
307
            legend.draw(image,
308
                g,
309
                viewPort,
310
                cancel,
311
                scale,
312
                null,
313
                getCoordTrans(),
314
                getFeatureStore(),
315
                featureQuery);
316
            
317
            logger.debug("Layer " + this.getName() + " drawn in " +
318
                (System.currentTimeMillis() - tini) + " milliseconds.");
319

    
320
        } catch (LegendException e) {
321
            this.setVisible(false);
322
            this.setActive(false);
323
            throw new ReadException(getName(), e);
324
        } finally {
325
            if (spatialCache.isEnabled()) {
326
                legend.deleteDrawingObserver(this);
327
            }
328
        }
329
    }
330

    
331
    public void print(Graphics2D g,
332
        ViewPort viewPort,
333
        Cancellable cancel,
334
        double scale,
335
        PrintAttributes properties) throws ReadException {
336
        if (!this.isWithinScale(scale)) {
337
            return;
338
        }
339
        if (cancel.isCanceled()) {
340
            return;
341
        }
342

    
343
        try {
344
            legend.print(g,
345
                viewPort,
346
                cancel,
347
                scale,
348
                null,
349
                getCoordTrans(),
350
                getFeatureStore(),
351
                null,
352
                properties);
353

    
354
        } catch (LegendException e) {
355
            this.setVisible(false);
356
            this.setActive(false);
357
            throw new ReadException(getName(), e);
358
        }
359
    }
360

    
361
    public void setLegend(IVectorLegend legend) throws LegendLayerException {
362
        if (this.legend == legend) {
363
            return;
364
        }
365
        if (this.legend != null && this.legend.equals(legend)) {
366
            return;
367
        }
368
        IVectorLegend oldLegend = this.legend;
369
        this.legend = legend;
370
        if (oldLegend != null) {
371
            oldLegend.removeLegendListener(this);
372
            oldLegend.deleteDrawingObserver(this);
373
        }
374
        if (legend != null) {
375
            this.legend.addDrawingObserver(this);
376
            this.legend.addLegendListener(this);
377
        }
378
        LegendChangedEvent e =
379
            LegendChangedEvent.createLegendChangedEvent(oldLegend, this.legend);
380
        e.setLayer(this);
381
        updateDrawVersion();
382
        callLegendChanged(e);
383
    }
384

    
385
    /**
386
     * Devuelve la Leyenda de la capa.
387
     * 
388
     * @return Leyenda.
389
     */
390
    public ILegend getLegend() {
391
        return legend;
392
    }
393

    
394
    public int getShapeType() throws ReadException {
395
            if (typeShape == -1) {
396
                    FeatureType featureType = null;
397
                    try {
398
                            if( getDataStore()!=null ){
399
                                    featureType =
400
                                            (((FeatureStore) getDataStore()).getDefaultFeatureType());
401
                            }
402
                    } catch (DataException e) {
403
                            throw new ReadException(getName(), e);
404
                    }
405
                    if( featureType!=null ){
406
                            int indexGeom = featureType.getDefaultGeometryAttributeIndex();
407
                            typeShape =
408
                                    featureType.getAttributeDescriptor(indexGeom).getGeometryType();
409
                    }
410
            }
411
            return typeShape;
412
    }
413

    
414
    /**
415
     * Returns the layer's geometry type
416
     * 
417
     * @return the geometry type
418
     * 
419
     * @throws ReadException
420
     *             if there is an error getting the geometry type
421
     */
422
    public GeometryType getGeometryType() throws ReadException {
423
        FeatureType featureType = null;
424
        try {
425
            if (getDataStore() != null) {
426
                featureType =
427
                    (((FeatureStore) getDataStore()).getDefaultFeatureType());
428
            }
429
        } catch (DataException e) {
430
            throw new ReadException(getName(), e);
431
        }
432
        return featureType == null ? null : featureType
433
            .getDefaultGeometryAttribute().getGeomType();
434
    }
435

    
436
    public void saveToState(PersistentState state) throws PersistenceException {
437

    
438
        if (!this.isAvailable()) {
439
            return;
440
        }
441

    
442
        super.saveToState(state);
443

    
444
        if (getLegend() != null) {
445
            state.set("legend", getLegend());
446
        }
447

    
448
        FeatureStore fst = null;
449
        fst = getFeatureStore();
450

    
451
        if (fst != null) {
452
            state.set("featureStore", fst);
453
        }
454

    
455
        state.set("isLabeled", isLabeled);
456

    
457
        if (strategy != null) {
458
            state.set("labelingStrategy", strategy);
459
        }
460

    
461
        if (getLinkProperties() != null) {
462
            state.set("linkProperties", getLinkProperties());
463
        }
464

    
465
        // state.set("bHasJoin", bHasJoin);
466
        state.set("typeShape", typeShape);
467
    }
468

    
469

    
470
    public void loadFromState(PersistentState state) throws PersistenceException {
471

    
472
        super.loadFromState(state);
473
        DataStore store = null;
474
        try {
475
                store = (DataStore) state.get("featureStore");
476
        } catch (PersistenceRuntimeException e) {
477
            logger.debug("Unable to load store from persistence in layer: " + this.getName(), e);
478
                        this.setAvailable(false);
479
                        return;
480
                }
481
        try {
482
            this.bindToDataStore(store);
483
        } catch (LoadLayerException e) {
484
            throw new PersistenceException("While loading FLyrVect from state.",
485
                e);
486
        }
487

    
488
        IVectorLegend lgnd = (IVectorLegend) state.get("legend");
489
        try {
490
            this.setLegend(lgnd);
491
        } catch (LegendLayerException e) {
492
            throw new PersistenceException("While loading FLyrVect from state.",
493
                e);
494
        }
495

    
496
        Boolean isLbl = new Boolean(false);
497
        ILabelingStrategy lblst = null;
498

    
499
        try {
500
            isLbl = (Boolean) state.get("isLabeled");
501
            if (isLbl.booleanValue()) {
502
                lblst = (ILabelingStrategy) state.get("labelingStrategy");
503
            }
504
        } catch (Exception ex) {
505
            throw new PersistenceException("While loading FLyrVect from state.",
506
                ex);
507
        }
508

    
509
        /*
510
         * String _labelFieldName = null;
511
         * String _labelfield = null;
512
         */
513

    
514
        if (isLbl.booleanValue()) {
515
            this.setIsLabeled(true);
516
            this.setLabelingStrategy(lblst);
517
        } else {
518
            this.setIsLabeled(false);
519
            this.setLabelingStrategy(null);
520
        }
521

    
522
        typeShape = state.getInt("typeShape");
523

    
524
    }
525

    
526
    /**
527
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
528
     * identifiquen la capa.
529
     * 
530
     * @return DOCUMENT ME!
531
     */
532
    public String toString() {
533
        /*
534
         * Se usa internamente para que la parte de datos identifique de forma
535
         * un?voca las tablas
536
         */
537
        String ret = super.toString();
538

    
539
        return "layer" + ret.substring(ret.indexOf('@') + 1);
540
    }
541

    
542
    public boolean isEditing() {
543
        FeatureStore fs = getFeatureStore();
544
        if (fs == null) {
545
            /*
546
             * This happens when layer is not available, for example,
547
             * it was not possible to load from persistence
548
             */
549
            return false;
550
        } else {
551
            return fs.isEditing();
552
        }
553
    }
554
    
555
    
556
    public void setEditing(boolean b) throws StartEditionLayerException {
557
        
558
        try {
559
            throw new RuntimeException();
560
        } catch (Throwable th) {
561
            logger.info("This method is deprecated. ", th);
562
        }
563
        
564
        if (b == super.isEditing()) {
565
            return;
566
        }
567
        
568
        super.setEditing(b);
569
        FeatureStore fs = getFeatureStore();
570
        if (b) {
571
            try {
572
                fs.edit();
573
            } catch (DataException e) {
574
                throw new StartEditionLayerException(getName(), e);
575
            }
576
        }
577
        setSpatialCacheEnabled(b);
578
        callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
579
    }
580

    
581

    
582
    /**
583
     * @deprecated Use {@link #getSpatialCache()}
584
     */
585
    public void clearSpatialCache() {
586
        spatialCache.clearAll();
587
    }
588

    
589
    /**
590
     * @deprecated Use {@link #getSpatialCache()}
591
     */
592
    public boolean isSpatialCacheEnabled() {
593
        return spatialCache.isEnabled();
594
    }
595

    
596
    /**
597
     * @deprecated Use {@link #getSpatialCache()}
598
     */
599
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
600
        spatialCache.setEnabled(spatialCacheEnabled);
601
    }
602

    
603
    public SpatialCache getSpatialCache() {
604
        return spatialCache;
605
    }
606

    
607
    /**
608
     * Siempre es un numero mayor de 1000
609
     * 
610
     * @param maxFeatures
611
     */
612
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
613
        if (maxFeatures > spatialCache.getMaxFeatures()) {
614
            spatialCache.setMaxFeatures(maxFeatures);
615
        }
616

    
617
    }
618

    
619
    /**
620
     * This method returns a boolean that is used by the FPopMenu
621
     * to make visible the properties menu or not. It is visible by
622
     * default, and if a later don't have to show this menu only
623
     * has to override this method.
624
     * 
625
     * @return
626
     *         If the properties menu is visible (or not)
627
     */
628
    public boolean isPropertiesMenuVisible() {
629
        return true;
630
    }
631

    
632
    public void reload() throws ReloadLayerException {
633
        super.reload();
634
        try {
635
            getFeatureStore().refresh();
636
        } catch (Exception e) {
637
            throw new ReloadLayerException(getName(), e);
638
        }
639
    }
640

    
641
    protected void setLoadSelection(Object xml) {
642
        // this.loadSelection = xml;
643
    }
644

    
645
    protected void setLoadLegend(IVectorLegend legend) {
646
        this.loadLegend = legend;
647
    }
648

    
649
    protected void putLoadSelection() {
650
        // if (this.loadSelection == null) return;
651
        // try {
652
        // this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
653
        // } catch (ReadDriverException e) {
654
        // throw new XMLException(e);
655
        // }
656
        // this.loadSelection = null;
657

    
658
    }
659

    
660
    protected void putLoadLegend() throws LegendLayerException {
661
        if (this.loadLegend == null) {
662
            return;
663
        }
664
        this.setLegend(this.loadLegend);
665
        this.loadLegend = null;
666
    }
667

    
668
    protected void cleanLoadOptions() {
669
        this.loadLegend = null;
670
    }
671

    
672
    public boolean isWritable() {
673
        return getFeatureStore().allowWrite();
674
    }
675

    
676
    public FLayer cloneLayer() throws Exception {
677
        FLyrVect clonedLayer = new FLyrVect();
678
        clonedLayer.bindToDataStore(getDataStore());
679
        // if (isJoined()) {
680
        // clonedLayer.setIsJoined(true);
681
        // }
682
        clonedLayer.setVisible(isVisible());
683
        // clonedLayer.setISpatialIndex(getISpatialIndex());
684
        clonedLayer.setName(getName());
685
        clonedLayer.setCoordTrans(getCoordTrans());
686

    
687
        clonedLayer.setLegend((IVectorLegend) getLegend().cloneLegend());
688

    
689
        clonedLayer.setIsLabeled(isLabeled());
690
        ILabelingStrategy labelingStrategy = getLabelingStrategy();
691
        if (labelingStrategy != null) {
692
            clonedLayer.setLabelingStrategy(labelingStrategy);
693
        }
694

    
695
        return clonedLayer;
696
    }
697

    
698
    protected boolean isOnePoint(AffineTransform graphicsTransform,
699
        ViewPort viewPort,
700
        double dpi,
701
        CartographicSupport csSym,
702
        Geometry geom,
703
        int[] xyCoords) {
704
        return isOnePoint(graphicsTransform, viewPort, geom, xyCoords)
705
            && csSym.getCartographicSize(viewPort, dpi, geom) <= 1;
706
    }
707

    
708
    private boolean isOnePoint(AffineTransform graphicsTransform,
709
        ViewPort viewPort,
710
        Geometry geom,
711
        int[] xyCoords) {
712
        boolean onePoint = false;
713
        int type = geom.getType();
714
        if (type == Geometry.TYPES.NULL) {
715
            return false;
716
        }
717
        if (type != Geometry.TYPES.POINT && type != Geometry.TYPES.MULTIPOINT) {
718

    
719
            Envelope geomBounds = geom.getEnvelope();
720

    
721
            // ICoordTrans ct = getCoordTrans();
722

    
723
            // Se supone que la geometria ya esta reproyectada
724
            // if (ct!=null) {
725
            // // geomBounds = ct.getInverted().convert(geomBounds);
726
            // geomBounds = geomBounds.convert(ct);
727
            // }
728

    
729
            double dist1Pixel = viewPort.getDist1pixel();
730

    
731
            onePoint =
732
                (geomBounds.getLength(0) <= dist1Pixel && geomBounds.getLength(1) <= dist1Pixel);
733

    
734
            if (onePoint) {
735
                // avoid out of range exceptions
736
                org.gvsig.fmap.geom.primitive.Point p;
737
                try {
738
                    p =
739
                        geomManager.createPoint(geomBounds.getMinimum(0),
740
                            geomBounds.getMinimum(1),
741
                            SUBTYPES.GEOM2D);
742
                    p.transform(viewPort.getAffineTransform());
743
                    p.transform(graphicsTransform);
744
                    xyCoords[0] = (int) p.getX();
745
                    xyCoords[1] = (int) p.getY();
746
                } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
747
                    logger.error("Error creating a point", e);
748
                }
749

    
750
            }
751

    
752
        }
753
        return onePoint;
754
    }
755

    
756
    public boolean isLabeled() {
757
        return isLabeled;
758
    }
759

    
760
    public void setIsLabeled(boolean isLabeled) {
761
        this.isLabeled = isLabeled;
762
    }
763

    
764
    public ILabelingStrategy getLabelingStrategy() {
765
        return strategy;
766
    }
767

    
768
    public void setLabelingStrategy(ILabelingStrategy strategy) {
769
        this.strategy = strategy;
770
        if (strategy == null) {
771
            return;
772
        }
773
        strategy.setLayer(this);
774
        updateDrawVersion();
775
    }
776

    
777
    public void drawLabels(BufferedImage image,
778
        Graphics2D g,
779
        ViewPort viewPort,
780
        Cancellable cancel,
781
        double scale,
782
        double dpi) throws ReadException {
783
        if (strategy != null && isWithinScale(scale)) {
784
            strategy.draw(image, g, viewPort, cancel, dpi);
785
        }
786
    }
787

    
788
    public void printLabels(Graphics2D g,
789
        ViewPort viewPort,
790
        Cancellable cancel,
791
        double scale,
792
        PrintAttributes properties) throws ReadException {
793
        if (strategy != null) {
794
            strategy.print(g, viewPort, cancel, properties);
795
        }
796
    }
797

    
798
    /**
799
     * Return true, because a Vectorial Layer supports HyperLink
800
     * 
801
     * @deprecated the hiperlink functionaliti is out the layer now
802
     */
803
    public boolean allowLinks() {
804
        return false;
805
    }
806

    
807
    public void load() throws LoadLayerException {
808
        super.load();
809
    }
810

    
811
    public FeatureStore getFeatureStore() {
812
        return (FeatureStore) getDataStore();
813
    }
814

    
815
    /**
816
     * @deprecated use instead {@link #queryByPoint(org.gvsig.fmap.geom.primitive.Point, double, FeatureType)}
817
     */
818
    public FeatureSet queryByPoint(Point2D mapPoint,
819
        double tol,
820
        FeatureType featureType) throws DataException {
821
        logger.warn("Deprecated use of queryByPoint.");
822
        GeometryManager manager = GeometryLocator.getGeometryManager();
823
        org.gvsig.fmap.geom.primitive.Point center;
824
        try {
825
            center =
826
                (org.gvsig.fmap.geom.primitive.Point) manager.create(TYPES.POINT,
827
                    SUBTYPES.GEOM2D);
828
            center.setX(mapPoint.getX());
829
            center.setY(mapPoint.getY());
830
            Circle circle =
831
                (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
832
            circle.setPoints(center, tol);
833
            return queryByGeometry(circle, featureType);
834
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
835
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
836
        }
837
    }
838

    
839
    public FeatureSet queryByPoint(org.gvsig.fmap.geom.primitive.Point point,
840
        double tol,
841
        FeatureType featureType) throws DataException {
842
        GeometryManager manager = GeometryLocator.getGeometryManager();
843
        try {
844
            Circle circle =
845
                (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
846
            circle.setPoints(point, tol);
847
            return queryByGeometry(circle, featureType);
848
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
849
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
850
        }
851
    }
852

    
853
    public FeatureSet queryByGeometry(Geometry geom, FeatureType featureType) throws DataException {
854
        FeatureQuery featureQuery = featureStore.createFeatureQuery();
855
        String geomName =
856
            featureStore.getDefaultFeatureType()
857
                .getDefaultGeometryAttributeName();
858
        featureQuery.setFeatureType(featureType);
859
        IntersectsGeometryEvaluator iee =
860
            new IntersectsGeometryEvaluator(geom,
861
                getMapContext().getViewPort().getProjection(),
862
                featureStore.getDefaultFeatureType(),
863
                geomName);
864
        featureQuery.setFilter(iee);
865
        featureQuery.setAttributeNames(null);
866
        return getFeatureStore().getFeatureSet(featureQuery);
867

    
868
    }
869

    
870
    /**
871
     * It return the {@link FeatureSet} that intersects with the envelope.
872
     * @param envelope
873
     *          envelope that defines the area for the query.
874
     * @param featureType
875
     *          only the features with this feature type are used in
876
     *          the query.    
877
     * @return
878
     *          the set of features that intersect with the envelope.
879
     * @throws DataException
880
     */
881
    public FeatureSet queryByEnvelope(Envelope envelope, FeatureType featureType) throws DataException {
882
        return queryByEnvelope(envelope, featureType, null);
883
    }
884

    
885
    /**
886
     * It return the {@link FeatureSet} that intersects with the envelope.
887
     * @param envelope
888
     *          envelope that defines the area for the query.
889
     * @param featureType
890
     *          only the features with this feature type are used in
891
     *          the query.
892
     * @param names
893
     *          the feature attributes that have to be checked.
894
     * @return
895
     *          the set of features that intersect with the envelope.
896
     * @throws DataException
897
     */
898
    public FeatureSet queryByEnvelope(Envelope envelope,
899
        FeatureType featureType,
900
        String[] names) throws DataException {
901
        FeatureQuery featureQuery = featureStore.createFeatureQuery();
902
        if (names == null) {
903
            featureQuery.setFeatureType(featureType);
904
        } else {
905
            featureQuery.setAttributeNames(names);
906
            featureQuery.setFeatureTypeId(featureType.getId());
907
        }
908
        String geomName =
909
            featureStore.getDefaultFeatureType()
910
                .getDefaultGeometryAttributeName();
911
        IntersectsGeometryEvaluator iee =
912
            new IntersectsGeometryEvaluator(envelope.getGeometry(),
913
                getMapContext().getViewPort().getProjection(),
914
                featureStore.getDefaultFeatureType(),
915
                geomName);
916
        featureQuery.setFilter(iee);
917
        return getFeatureStore().getFeatureSet(featureQuery);
918

    
919
    }
920

    
921
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel) throws LoadLayerException,
922
        DataException {
923

    
924
        return getInfo(p, tolerance, cancel, true);
925
    }
926

    
927
    public DynObjectSet getInfo(Point p,
928
        double tolerance,
929
        Cancellable cancel,
930
        boolean fast) throws LoadLayerException, DataException {
931
        Point2D infop = new Point2D.Double(p.x, p.y);
932
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(infop);
933
        return queryByPoint(pReal,
934
            tolerance,
935
            getFeatureStore().getDefaultFeatureType()).getDynObjectSet(fast);
936
    }
937

    
938
    public DynObjectSet getInfo(org.gvsig.fmap.geom.primitive.Point p,
939
        double tolerance) throws LoadLayerException, DataException {
940
        return queryByPoint(p,tolerance, getFeatureStore().getDefaultFeatureType()).getDynObjectSet(false);
941
    }
942
    
943
    public void legendCleared(LegendClearEvent event) {
944
        this.updateDrawVersion();
945
        LegendChangedEvent e =
946
            LegendChangedEvent.createLegendChangedEvent(legend, legend);
947
        this.callLegendChanged(e);
948
    }
949

    
950
    public boolean symbolChanged(SymbolLegendEvent e) {
951
        this.updateDrawVersion();
952
        LegendChangedEvent ev =
953
            LegendChangedEvent.createLegendChangedEvent(legend, legend);
954
        this.callLegendChanged(ev);
955
        return true;
956
    }
957

    
958
    public void update(Observable observable, Object notification) {
959
        if (observable.equals(this.featureStore)) {
960
            if (notification instanceof FeatureStoreNotification) {
961
                FeatureStoreNotification event =
962
                    (FeatureStoreNotification) notification;
963
                if (event.getType() == FeatureStoreNotification.AFTER_DELETE
964
                    || event.getType() == FeatureStoreNotification.AFTER_UNDO
965
                    || event.getType() == FeatureStoreNotification.AFTER_REDO
966
                    || event.getType() == FeatureStoreNotification.AFTER_REFRESH
967
                    || event.getType() == FeatureStoreNotification.AFTER_UPDATE
968
                    || event.getType() == FeatureStoreNotification.AFTER_UPDATE_TYPE
969
                    || event.getType() == FeatureStoreNotification.SELECTION_CHANGE
970
                    || event.getType() == FeatureStoreNotification.AFTER_INSERT) {
971
                    this.updateDrawVersion();
972
                    
973
                } else if (event.getType() == FeatureStoreNotification.AFTER_CANCELEDITING) {
974
                    
975
                    setSpatialCacheEnabled(false);
976
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
977
                    this.updateDrawVersion();
978
                    
979
                } else if (event.getType() == FeatureStoreNotification.AFTER_STARTEDITING) {
980
                    
981
                    setSpatialCacheEnabled(true);
982
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
983

    
984
                } else if (event.getType() == FeatureStoreNotification.TRANSFORM_CHANGE){
985
                    //If a transform has to be applied, try to reload the layer.
986
                    try {
987
                        reload();
988
                    } catch (ReloadLayerException e) {
989
                        this.setAvailable(false);
990
                    }
991
                } else if (event.getType() == FeatureStoreNotification.RESOURCE_CHANGED) {
992
                    this.setAvailable(false);
993
                } else         if (event.getType() == FeatureStoreNotification.AFTER_FINISHEDITING) {
994
                    this.setAvailable(true);
995
                    setSpatialCacheEnabled(false);
996
                    callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
997
                    this.updateDrawVersion();
998
                }
999
            }
1000
        }
1001
        else if (notification instanceof FeatureDrawnNotification
1002
            && isEditing()) {
1003
            // This code is needed only on edition.
1004
            Geometry geometry =
1005
                ((FeatureDrawnNotification) notification).getDrawnGeometry();
1006
            spatialCache.insert(geometry.getEnvelope(), geometry);
1007
        }
1008
    }
1009

    
1010
    /*
1011
     * (non-Javadoc)
1012
     * 
1013
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1014
     */
1015
    public Set getMetadataChildren() {
1016
        Set ret = new TreeSet();
1017
        ret.add(this.featureStore);
1018
        return ret;
1019
    }
1020

    
1021
    /*
1022
     * (non-Javadoc)
1023
     * 
1024
     * @see org.gvsig.metadata.Metadata#getMetadataID()
1025
     */
1026
    public Object getMetadataID() throws MetadataException {
1027
        return "Layer(" + this.getName() + "):"
1028
            + this.featureStore.getMetadataID();
1029
    }
1030

    
1031
    
1032

    
1033
    public GeometryType getTypeVectorLayer() throws DataException,
1034
        LocatorException,
1035
        GeometryTypeNotSupportedException,
1036
        GeometryTypeNotValidException {
1037
        // FIXME Esto deberia de pedirse a FType!!!!
1038
        FeatureStore fs = this.getFeatureStore();
1039
        FeatureType fType = fs.getDefaultFeatureType();
1040
        FeatureAttributeDescriptor attr =
1041
            fType.getAttributeDescriptor(fType.getDefaultGeometryAttributeIndex());
1042
        GeometryType geomType =
1043
            GeometryLocator.getGeometryManager()
1044
                .getGeometryType(attr.getGeometryType(),
1045
                    attr.getGeometrySubType());
1046
        return geomType;
1047
    }
1048

    
1049
    public static void registerPersistent() {
1050
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1051
        if (manager.getDefinition(FLyrDefault.class) == null) {
1052
            FLyrDefault.registerPersistent();
1053
        }
1054
        DynStruct definition =
1055
            manager.addDefinition(FLyrVect.class,
1056
                "FLyrVect",
1057
                "FLyrVect Persistence definition",
1058
                null,
1059
                null);
1060
        definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE,
1061
            "FLyrDefault");
1062

    
1063
        definition.addDynFieldObject("legend")
1064
            .setClassOfValue(IVectorLegend.class)
1065
            .setMandatory(true);
1066
        definition.addDynFieldObject("featureStore")
1067
            .setClassOfValue(FeatureStore.class)
1068
            .setMandatory(true);
1069
        definition.addDynFieldBoolean("isLabeled").setMandatory(true);
1070
        definition.addDynFieldInt("typeShape").setMandatory(true);
1071
        definition.addDynFieldObject("labelingStrategy")
1072
            .setClassOfValue(ILabelingStrategy.class)
1073
            .setMandatory(false);
1074

    
1075
    }
1076

    
1077
    protected void doDispose() throws BaseException {
1078
        dispose(featureStore);
1079
        spatialCache.clearAll();
1080
    }
1081
}