Statistics
| Revision:

root / branches / dal_time_support / libraries / libFMap_mapcontext / src / org / gvsig / fmap / mapcontext / layers / vectorial / FLyrVect.java @ 35201

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

    
116
/**
117
 * Capa b?sica Vectorial.
118
 * 
119
 * @author Fernando Gonz?lez Cort?s
120
 */
121

    
122
public class FLyrVect extends FLyrDefault implements VectorLayer,
123
    LegendContentsChangedListener, Observer {
124

    
125
    final static private org.slf4j.Logger logger =
126
        LoggerFactory.getLogger(FLyrVect.class);
127
    private final GeometryManager geomManager =
128
        GeometryLocator.getGeometryManager();
129

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

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

    
142
    private boolean isLabeled;
143
    protected ILabelingStrategy strategy;
144

    
145
    public FLyrVect() {
146
        super();
147
    }
148

    
149
    /**
150
     * Devuelve el VectorialAdapater de la capa.
151
     * 
152
     * @return VectorialAdapter.
153
     */
154
    public DataStore getDataStore() {
155
        if (!this.isAvailable()) {
156
            return null;
157
        }
158
        return featureStore;
159
    }
160

    
161
    /**
162
     * If we use a persistent spatial index associated with this layer, and the
163
     * index is not intrisic to the layer (for example spatial databases) this
164
     * method looks for existent spatial index, and loads it.
165
     * 
166
     */
167
    // private void loadSpatialIndex() {
168
    // //FIXME: Al abrir el indice en fichero...
169
    // //?C?mo lo liberamos? un metodo Layer.shutdown()
170
    //
171
    //
172
    // ReadableVectorial source = getSource();
173
    // //REVISAR QUE PASA CON LOS DRIVERS DXF, DGN, etc.
174
    // //PUES SON VECTORIALFILEADAPTER
175
    // if (!(source instanceof VectorialFileAdapter)) {
176
    // // we are not interested in db adapters
177
    // return;
178
    // }
179
    // VectorialDriver driver = source.getDriver();
180
    // if (!(driver instanceof BoundedShapes)) {
181
    // // we dont spatially index layers that are not bounded
182
    // return;
183
    // }
184
    // File file = ((VectorialFileAdapter) source).getFile();
185
    // String fileName = file.getAbsolutePath();
186
    // File sptFile = new File(fileName + ".qix");
187
    // if (!sptFile.exists() || (!(sptFile.length() > 0))) {
188
    // // before to exit, look for it in temp path
189
    // String tempPath = System.getProperty("java.io.tmpdir");
190
    // fileName = tempPath + File.separator + sptFile.getName();
191
    // sptFile = new File(fileName);
192
    // // it doesnt exists, must to create
193
    // if (!sptFile.exists() || (!(sptFile.length() > 0))) {
194
    // return;
195
    // }// if
196
    // }// if
197
    //
198
    // try {
199
    // source.start();
200
    // spatialIndex = new
201
    // QuadtreeGt2(FileUtils.getFileWithoutExtension(sptFile),
202
    // "NM", source.getFullExtent(), source.getShapeCount(), false);
203
    // source.setSpatialIndex(spatialIndex);
204
    // } catch (SpatialIndexException e) {
205
    // spatialIndex = null;
206
    // e.printStackTrace();
207
    // return;
208
    // } catch (ReadDriverException e) {
209
    // spatialIndex = null;
210
    // e.printStackTrace();
211
    // return;
212
    // }
213
    //
214
    // }
215

    
216
    /**
217
     * Checks if it has associated an external spatial index
218
     * (an spatial index file).
219
     * 
220
     * It looks for it in main file path, or in temp system path.
221
     * If main file is rivers.shp, it looks for a file called
222
     * rivers.shp.qix.
223
     * 
224
     * @return
225
     */
226
    // public boolean isExternallySpatiallyIndexed() {
227
    // /*
228
    // * FIXME (AZABALA): Independizar del tipo de fichero de ?ndice
229
    // * con el que se trabaje (ahora mismo considera la extension .qix,
230
    // * pero esto depender? del tipo de ?ndice)
231
    // * */
232
    // ReadableVectorial source = getSource();
233
    // if (!(source instanceof VectorialFileAdapter)) {
234
    // // we are not interested in db adapters.
235
    // // think in non spatial dbs, like HSQLDB
236
    // return false;
237
    // }
238
    // File file = ((VectorialFileAdapter) source).getFile();
239
    // String fileName = file.getAbsolutePath();
240
    // File sptFile = new File(fileName + ".qix");
241
    // if (!sptFile.exists() || (!(sptFile.length() > 0))) {
242
    // // before to exit, look for it in temp path
243
    // // it doesnt exists, must to create
244
    // String tempPath = System.getProperty("java.io.tmpdir");
245
    // fileName = tempPath + File.separator + sptFile.getName();
246
    // sptFile = new File(fileName);
247
    // if (!sptFile.exists() || (!(sptFile.length() > 0))) {
248
    // return false;
249
    // }// if
250
    // }// if
251
    // return true;
252
    // }
253
    /**
254
     * Inserta el VectorialAdapter a la capa.
255
     * 
256
     * @param va
257
     *            VectorialAdapter.
258
     * 
259
     * @deprecated esto deber?a se ser protected
260
     */
261
    public void setDataStore(DataStore dataStore) throws LoadLayerException {
262
        if (this.featureStore != null && this.featureStore != dataStore) {
263
            this.featureStore.deleteObserver(this);
264
        }
265

    
266
        featureStore = (FeatureStore) dataStore;
267

    
268
        IVectorLegend legend =
269
                (IVectorLegend) MapContextLocator.getMapContextManager().getLegend(dataStore);
270

    
271
        if (legend == null) {
272
            throw new LegendLayerException(this.getName());
273
        }
274

    
275
        this.setLegend(legend);
276

    
277
        ILabelingStrategy labeler = null;
278
        try {
279
            labeler =
280
                (ILabelingStrategy) dataStore.invokeDynMethod("getLabeling",
281
                    null);
282
        } catch (DynMethodNotSupportedException e1) {
283
            labeler = null;
284
        } catch (DynMethodException e1) {
285
            logger.error("Can't load the specific lebeling strategy provided for the layer {}.",
286
                this.getName(),
287
                e1);
288
        }
289

    
290
        if (labeler != null) {
291
            labeler.setLayer(this);
292
            this.setLabelingStrategy(labeler);
293
            this.setIsLabeled(true); // TODO: ac? no s'hauria de detectar si t?
294
                                     // etiquetes?????
295
        }
296

    
297
        this.delegate(dataStore);
298

    
299
        dataStore.addObserver(this);
300

    
301
        ToolsLocator.getDisposableManager().bind(dataStore);
302
    }
303

    
304
    public Envelope getFullEnvelope() throws ReadException {
305
        Envelope rAux;
306
        try {
307
            rAux = getFeatureStore().getEnvelope();
308
        } catch (BaseException e) {
309
            throw new ReadException(getName(), e);
310
        }
311

    
312
        // Esto es para cuando se crea una capa nueva con el fullExtent de ancho
313
        // y alto 0.
314
        if (rAux == null || rAux.getMaximum(0) - rAux.getMinimum(0) == 0
315
            && rAux.getMaximum(1) - rAux.getMinimum(1) == 0) {
316
            try {
317
                rAux =
318
                    geomManager.createEnvelope(0, 0, 100, 100, SUBTYPES.GEOM2D);
319
            } catch (CreateEnvelopeException e) {
320
                logger.error("Error creating the envelope", e);
321
                e.printStackTrace();
322
            }
323
        }
324
        // Si existe reproyecci?n, reproyectar el extent
325
        ICoordTrans ct = getCoordTrans();
326
        try {
327
            if (ct != null) {
328
                Point2D pt1 =
329
                    new Point2D.Double(rAux.getMinimum(0), rAux.getMinimum(1));
330
                Point2D pt2 =
331
                    new Point2D.Double(rAux.getMaximum(0), rAux.getMaximum(1));
332
                pt1 = ct.convert(pt1, null);
333
                pt2 = ct.convert(pt2, null);
334
                try {
335
                    rAux =
336
                        geomManager.createEnvelope(pt1.getX(),
337
                            pt1.getY(),
338
                            pt2.getX(),
339
                            pt2.getY(),
340
                            SUBTYPES.GEOM2D);
341
                } catch (CreateEnvelopeException e) {
342
                    logger.error("Error creating the envelope", e);
343
                    e.printStackTrace();
344
                }// new Rectangle2D.Double();
345
            }
346
        } catch (IllegalStateException e) {
347
            this.setAvailable(false);
348
            this.addError(new ReprojectLayerException(getName(), e));
349
        }
350
        return rAux;
351

    
352
    }
353

    
354
    /**
355
     * Draws using IFeatureIterator. This method will replace the old draw(...)
356
     * one.
357
     * 
358
     * @autor jaume dominguez faus - jaume.dominguez@iver.es
359
     * @param image
360
     * @param g
361
     * @param viewPort
362
     * @param cancel
363
     * @param scale
364
     * @throws ReadDriverException
365
     */
366
    public void draw(BufferedImage image,
367
        Graphics2D g,
368
        ViewPort viewPort,
369
        Cancellable cancel,
370
        double scale) throws ReadException {
371

    
372
        if (legend == null) {
373
            return;
374
        }
375

    
376
        if (!this.isWithinScale(scale)) {
377
            return;
378
        }
379
        if (cancel.isCanceled()) {
380
            return;
381
        }
382

    
383
        if (spatialCache.isEnabled()) {
384
            spatialCache.clearAll();
385
            legend.addDrawingObserver(this);
386
        }
387

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

    
399
        } catch (LegendException e) {
400
            this.setVisible(false);
401
            this.setActive(false);
402
            throw new ReadException(getName(), e);
403
        } finally {
404
            if (spatialCache.isEnabled()) {
405
                legend.deleteDrawingObserver(this);
406
            }
407
        }
408
    }
409

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

    
422
        try {
423
            legend.print(g,
424
                viewPort,
425
                cancel,
426
                scale,
427
                null,
428
                getCoordTrans(),
429
                getFeatureStore(),
430
                null,
431
                properties);
432

    
433
        } catch (LegendException e) {
434
            this.setVisible(false);
435
            this.setActive(false);
436
            throw new ReadException(getName(), e);
437
        }
438
    }
439

    
440
    /**
441
     * <p>
442
     * Creates an spatial index associated to this layer. The spatial index will
443
     * used the native projection of the layer, so if the layer is reprojected,
444
     * it will be ignored.
445
     * </p>
446
     * 
447
     * @param cancelMonitor
448
     *            instance of CancellableMonitorable that allows
449
     *            to monitor progress of spatial index creation, and cancel the
450
     *            process
451
     */
452
    // public void createSpatialIndex(CancellableMonitorable cancelMonitor){
453
    // // FJP: ESTO HABR? QUE CAMBIARLO. PARA LAS CAPAS SECUENCIALES, TENDREMOS
454
    // // QUE ACCEDER CON UN WHILE NEXT. (O mejorar lo de los FeatureVisitor
455
    // // para que acepten recorrer sin geometria, solo con rectangulos.
456
    //
457
    // //If this vectorial layer is based in a spatial database, the spatial
458
    // //index is already implicit. We only will index file drivers
459
    // ReadableVectorial va = getSource();
460
    // //We must think in non spatial databases, like HSQLDB
461
    // if(!(va instanceof VectorialFileAdapter)){
462
    // return;
463
    // }
464
    // if (!(va.getDriver() instanceof BoundedShapes)) {
465
    // return;
466
    // }
467
    // File file = ((VectorialFileAdapter) va).getFile();
468
    // String fileName = file.getAbsolutePath();
469
    // ISpatialIndex localCopy = null;
470
    // try {
471
    // va.start();
472
    // localCopy = new QuadtreeGt2(fileName, "NM", va.getFullExtent(),
473
    // va.getShapeCount(), true);
474
    //
475
    // } catch (SpatialIndexException e1) {
476
    // // Probably we dont have writing permissions
477
    // String directoryName = System.getProperty("java.io.tmpdir");
478
    // File newFile = new File(directoryName +
479
    // File.separator +
480
    // file.getName());
481
    // String newFileName = newFile.getName();
482
    // try {
483
    // localCopy = new QuadtreeGt2(newFileName, "NM", va.getFullExtent(),
484
    // va.getShapeCount(), true);
485
    // } catch (SpatialIndexException e) {
486
    // // if we cant build a file based spatial index, we'll build
487
    // // a pure memory spatial index
488
    // localCopy = new QuadtreeJts();
489
    // } catch (ReadException e) {
490
    // localCopy = new QuadtreeJts();
491
    // }
492
    //
493
    // } catch(Exception e){
494
    // e.printStackTrace();
495
    // }//try
496
    // BoundedShapes shapeBounds = (BoundedShapes) va.getDriver();
497
    // try {
498
    // for (int i=0; i < va.getShapeCount(); i++)
499
    // {
500
    // if(cancelMonitor != null){
501
    // if(cancelMonitor.isCanceled())
502
    // return;
503
    // cancelMonitor.reportStep();
504
    // }
505
    // Rectangle2D r = shapeBounds.getShapeBounds(i);
506
    // if(r != null)
507
    // localCopy.insert(r, i);
508
    // } // for
509
    // va.stop();
510
    // if(localCopy instanceof IPersistentSpatialIndex)
511
    // ((IPersistentSpatialIndex) localCopy).flush();
512
    // spatialIndex = localCopy;
513
    // //vectorial adapter needs a reference to the spatial index, to solve
514
    // //request for feature iteration based in spatial queries
515
    // source.setSpatialIndex(spatialIndex);
516
    // } catch (ReadException e) {
517
    // // TODO Auto-generated catch block
518
    // e.printStackTrace();
519
    // }
520
    // }
521

    
522
    // public void createSpatialIndex() {
523
    // createSpatialIndex(null);
524
    // }
525

    
526
    public void setLegend(IVectorLegend legend) throws LegendLayerException {
527
        if (this.legend == legend) {
528
            return;
529
        }
530
        if (this.legend != null && this.legend.equals(legend)) {
531
            return;
532
        }
533
        IVectorLegend oldLegend = this.legend;
534
        this.legend = legend;
535
        if (oldLegend != null) {
536
            oldLegend.removeLegendListener(this);
537
            oldLegend.deleteDrawingObserver(this);
538
        }
539
        if (legend != null) {
540
            this.legend.addDrawingObserver(this);
541
            this.legend.addLegendListener(this);
542
        }
543
        LegendChangedEvent e =
544
            LegendChangedEvent.createLegendChangedEvent(oldLegend, this.legend);
545
        e.setLayer(this);
546
        callLegendChanged(e);
547
    }
548

    
549
    /**
550
     * Devuelve la Leyenda de la capa.
551
     * 
552
     * @return Leyenda.
553
     */
554
    public ILegend getLegend() {
555
        return legend;
556
    }
557

    
558
    /**
559
     * Devuelve el tipo de shape que contiene la capa.
560
     * 
561
     * @return tipo de shape.
562
     * 
563
     * @throws ReadException
564
     */
565
    public int getShapeType() throws ReadException {
566
        if (typeShape == -1) {
567
            FeatureType featureType;
568
            try {
569
                featureType =
570
                    (((FeatureStore) getDataStore()).getDefaultFeatureType());
571
            } catch (DataException e) {
572
                throw new ReadException(getName(), e);
573
            }
574
            int indexGeom = featureType.getDefaultGeometryAttributeIndex();
575
            typeShape =
576
                featureType.getAttributeDescriptor(indexGeom).getGeometryType();
577
        }
578
        return typeShape;
579
    }
580

    
581
    public void saveToState(PersistentState state) throws PersistenceException {
582

    
583
        if (!this.isAvailable()) {
584
            return;
585
        }
586

    
587
        super.saveToState(state);
588

    
589
        if (getLegend() != null) {
590
            state.set("legend", getLegend());
591
        }
592

    
593
        FeatureStore fst = null;
594
        fst = getFeatureStore();
595

    
596
        if (fst != null) {
597
            state.set("featureStore", fst);
598
        }
599

    
600
        state.set("isLabeled", isLabeled);
601

    
602
        if (strategy != null) {
603
            state.set("labelingStrategy", strategy);
604
        }
605

    
606
        if (getLinkProperties() != null) {
607
            state.set("linkProperties", getLinkProperties());
608
        }
609

    
610
        // state.set("bHasJoin", bHasJoin);
611
        state.set("typeShape", typeShape);
612
    }
613

    
614
    // public XMLEntity getXMLEntity() throws XMLException {
615
    //
616
    // if (!this.isAvailable() && this.orgXMLEntity != null) {
617
    // return this.orgXMLEntity;
618
    // }
619
    // XMLEntity xml = super.getXMLEntity();
620
    // if (getLegend()!=null){
621
    // XMLEntity xmlLegend=getLegend().getXMLEntity();
622
    // xmlLegend.putProperty("tagName","legend");
623
    // xml.addChild(xmlLegend);
624
    // }
625
    // try {
626
    // PersistenceManager manager = ToolsLocator.getPersistenceManager();
627
    // PersistentState stateFeatureStore=manager.getState(getFeatureStore());
628
    // stateFeatureStore.set("tagName","featureStore");
629
    // xml.addChild(((XMLEntityState)stateFeatureStore).getXMLEntity());
630
    // } catch (ReadException e) {
631
    // throw new XMLLayerException(getName(),e);
632
    // } catch (PersistenceException e) {
633
    // throw new XMLLayerException(getName(),e);
634
    // }
635
    // // properties from ILabelable
636
    // xml.putProperty("isLabeled", isLabeled);
637
    // if (strategy != null) {
638
    // XMLEntity strategyXML = strategy.getXMLEntity();
639
    // strategyXML.putProperty("tagName", "labelingStrategy");
640
    // xml.addChild(strategy.getXMLEntity());
641
    // }
642
    // xml.addChild(getLinkProperties().getXMLEntity());
643
    // return xml;
644
    // }
645

    
646
    public void loadFromState(PersistentState state) throws PersistenceException {
647

    
648
        super.loadFromState(state);
649

    
650
        DataStore store = (DataStore) state.get("featureStore");
651
        try {
652
            this.setDataStore(store);
653
        } catch (LoadLayerException e) {
654
            throw new PersistenceException("While loading FLyrVect from state.",
655
                e);
656
        }
657

    
658
        IVectorLegend lgnd = (IVectorLegend) state.get("legend");
659
        try {
660
            this.setLegend(lgnd);
661
        } catch (LegendLayerException e) {
662
            throw new PersistenceException("While loading FLyrVect from state.",
663
                e);
664
        }
665

    
666
        Boolean isLbl = new Boolean(false);
667
        ILabelingStrategy lblst = null;
668

    
669
        try {
670
            isLbl = (Boolean) state.get("isLabeled");
671
            if (isLbl.booleanValue()) {
672
                lblst = (ILabelingStrategy) state.get("labelingStrategy");
673
            }
674
        } catch (Exception ex) {
675
            throw new PersistenceException("While loading FLyrVect from state.",
676
                ex);
677
        }
678

    
679
        /*
680
         * String _labelFieldName = null;
681
         * String _labelfield = null;
682
         */
683

    
684
        if (isLbl.booleanValue()) {
685
            this.setIsLabeled(true);
686
            this.setLabelingStrategy(lblst);
687
        } else {
688
            this.setIsLabeled(false);
689
            this.setLabelingStrategy(null);
690
        }
691

    
692
        // try {
693
        // linkProperties = (FLyrVectLinkProperties)
694
        // state.get("linkProperties");
695
        // } catch (PersistenceException pex) {
696
        // // not mandatory
697
        // linkProperties = null;
698
        // }
699

    
700
        // bHasJoin = state.getBoolean("bHasJoin");
701
        typeShape = state.getInt("typeShape");
702

    
703
        // try { _labelFieldName = state.getString("labelFieldName"); } catch
704
        // (PersistenceException ex) {
705
        // _labelFieldName = null;
706
        // }
707
        // try { _labelfield = state.getString("labelfield"); } catch
708
        // (PersistenceException ex) {
709
        // _labelfield = null;
710
        // }
711

    
712
        // ILabelingStrategy not implemented
713
        // if (_labelFieldName != null) {
714
        //
715
        // AttrInTableLabelingStrategy labeling = new
716
        // AttrInTableLabelingStrategy();
717
        // try {
718
        // labeling.setLayer(this);
719
        // } catch (ReadException e) {
720
        // logger.error("While setting layer to AttrInTableLabelingStrategy: " +
721
        // e.getMessage());
722
        // }
723
        // labeling.setUsesFixedSize(true);
724
        // labeling.setFixedSize(10);
725
        // labeling.setTextField(_labelFieldName);
726
        // labeling.setHeightField(state.getString("labelHeightFieldName"));
727
        // labeling.setRotationField(state.getString("labelRotationFieldName"));
728
        // setLabelingStrategy(labeling);
729
        // setIsLabeled(true);
730
        //
731
        // } else {
732
        // if (_labelfield != null) {
733
        //
734
        // AttrInTableLabelingStrategy labeling = new
735
        // AttrInTableLabelingStrategy();
736
        // try {
737
        // labeling.setLayer(this);
738
        // } catch (ReadException e) {
739
        // logger.error("While setting layer to AttrInTableLabelingStrategy: " +
740
        // e.getMessage());
741
        // }
742
        // labeling.setUsesFixedSize(true);
743
        // labeling.setFixedSize(10);
744
        // labeling.setTextField(_labelfield);
745
        // labeling.setHeightField(state.getString("labelFieldHeight"));
746
        // labeling.setRotationField(state.getString("labelFieldRotation"));
747
        // setLabelingStrategy(labeling);
748
        // setIsLabeled(true);
749
        // }
750
        // }
751

    
752
    }
753

    
754
    // public void setXMLEntity(XMLEntity xml) throws XMLException {
755
    // try {
756
    // super.setXMLEntity(xml);
757
    // XMLEntity legendXML = xml.firstChild("tagName","legend");
758
    // IVectorLegend leg = LegendFactory.createFromXML(legendXML);
759
    //
760
    // // PersistentState persistentState=new XMLEntityState(new
761
    // XMLEntityManager());
762
    // XMLEntity xmlStore=xml.firstChild("tagName","featureStore");
763
    // XMLEntityManager xmlManger = new XMLEntityManager();
764
    // PersistentState state = xmlManger.createState(xmlStore);
765
    // DataStore store = (DataStore)
766
    // ToolsLocator.getPersistenceManager().create(state);
767
    // // persistentState.createState(xmlStore);
768
    //
769
    // // DataManager dm=DALLocator.getDataManager();
770
    //
771
    // this.setDataStore(store);
772
    // /* end patch */
773
    // try {
774
    // setLegend(leg);
775
    // } catch (LegendLayerException e) {
776
    // throw new XMLLegendException(e);
777
    // }
778
    // // set properties for ILabelable
779
    //
780
    // if (xml.contains("isLabeled")
781
    // && xml.getBooleanProperty(("isLabeled"))) {
782
    // XMLEntity labelingXML = xml.firstChild("tagName", "labelingStrategy");
783
    // if (labelingXML != null){
784
    //
785
    // isLabeled = true;
786
    // try {
787
    // this.strategy = LabelingFactory.createStrategyFromXML(labelingXML, this);
788
    // } catch (NotExistInXMLEntity neXMLEX) {
789
    // // no strategy was set, just continue;
790
    // logger.warn("Reached what should be unreachable code");
791
    // }
792
    // } else {
793
    // isLabeled = false;
794
    // }
795
    // } else if (legendXML.contains("labelFieldName")||
796
    // legendXML.contains("labelfield")) {
797
    // /* (jaume) begin patch;
798
    // * for backward compatibility purposes. Since gvSIG v1.1 labeling is
799
    // * no longer managed by the Legend but by the ILabelingStrategy. The
800
    // * following allows restoring older projects' labelings.
801
    // */
802
    // String labelTextField = null;
803
    // if (legendXML.contains("labelFieldName")){
804
    // labelTextField = legendXML.getStringProperty("labelFieldName");
805
    // if (labelTextField != null) {
806
    // AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
807
    // labeling.setLayer(this);
808
    // labeling.setUsesFixedSize(true);
809
    // labeling.setFixedSize(10);
810
    // labeling.setTextField(labelTextField);
811
    // labeling.setHeightField(legendXML.getStringProperty("labelHeightFieldName"));
812
    // labeling.setRotationField(legendXML.getStringProperty("labelRotationFieldName"));
813
    // this.setLabelingStrategy(labeling);
814
    // this.setIsLabeled(true);
815
    // }
816
    // }else{
817
    // labelTextField = legendXML.getStringProperty("labelfield");
818
    // if (labelTextField != null) {
819
    // AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
820
    // labeling.setLayer(this);
821
    // labeling.setUsesFixedSize(true);
822
    // labeling.setFixedSize(10);
823
    // labeling.setTextField(labelTextField);
824
    // labeling.setHeightField(legendXML.getStringProperty("labelFieldHeight"));
825
    // labeling.setRotationField(legendXML.getStringProperty("labelFieldRotation"));
826
    // this.setLabelingStrategy(labeling);
827
    // this.setIsLabeled(true);
828
    // }
829
    // }
830
    // }else{
831
    // isLabeled = false;
832
    // }
833
    // XMLEntity xmlLinkProperties=xml.firstChild("typeChild","linkProperties");
834
    // if (xmlLinkProperties != null){
835
    // getLinkProperties().setXMLEntity(xmlLinkProperties);
836
    // }
837
    // } catch (Exception e) {
838
    // e.printStackTrace();
839
    // this.setAvailable(false);
840
    // this.orgXMLEntity = xml;
841
    //
842
    // }
843
    // //
844
    //
845
    // }
846

    
847
    /**
848
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
849
     * identifiquen la capa.
850
     * 
851
     * @return DOCUMENT ME!
852
     */
853
    public String toString() {
854
        /*
855
         * Se usa internamente para que la parte de datos identifique de forma
856
         * un?voca las tablas
857
         */
858
        String ret = super.toString();
859

    
860
        return "layer" + ret.substring(ret.indexOf('@') + 1);
861
    }
862

    
863
    // public boolean isJoined() {
864
    // return bHasJoin;
865
    // }
866

    
867
    /**
868
     * Returns if a layer is spatially indexed
869
     * 
870
     * @return if this layer has the ability to proces spatial queries without
871
     *         secuential scans.
872
     * @throws StopEditionLayerException 
873
     */
874
    // public boolean isSpatiallyIndexed() {
875
    // ReadableVectorial source = getSource();
876
    // if (source instanceof ISpatialDB)
877
    // return true;
878
    //
879
    // //FIXME azabala
880
    // /*
881
    // * Esto es muy dudoso, y puede cambiar.
882
    // * Estoy diciendo que las que no son fichero o no son
883
    // * BoundedShapes estan indexadas. Esto es mentira, pero
884
    // * as? quien pregunte no querr? generar el indice.
885
    // * Esta por ver si interesa generar el indice para capas
886
    // * HSQLDB, WFS, etc.
887
    // */
888
    // if(!(source instanceof VectorialFileAdapter)){
889
    // return true;
890
    // }
891
    // if (!(source.getDriver() instanceof BoundedShapes)) {
892
    // return true;
893
    // }
894
    //
895
    // if (getISpatialIndex() != null)
896
    // return true;
897
    // return false;
898
    // }
899
    //
900
    // public void setIsJoined(boolean hasJoin) {
901
    // bHasJoin = hasJoin;
902
    // }
903

    
904
    // /**
905
    // * @return Returns the spatialIndex.
906
    // */
907
    // public ISpatialIndex getISpatialIndex() {
908
    // return spatialIndex;
909
    // }
910
    // /**
911
    // * Sets the spatial index. This could be useful if, for some
912
    // * reasons, you want to work with a distinct spatial index
913
    // * (for example, a spatial index which could makes nearest
914
    // * neighbour querys)
915
    // * @param spatialIndex
916
    // */
917
    // public void setISpatialIndex(ISpatialIndex spatialIndex){
918
    // this.spatialIndex = spatialIndex;
919
    // }
920

    
921
    public void setEditing(boolean b) throws StartEditionLayerException {
922
        super.setEditing(b);
923
        FeatureStore fs = getFeatureStore();
924
        if (b) {
925
            try {
926
                fs.edit();
927
            } catch (ReadException e) {
928
                throw new StartEditionLayerException(getName(), e);
929
            } catch (DataException e) {
930
                throw new StartEditionLayerException(getName(), e);
931
            }
932
        }
933
        setSpatialCacheEnabled(b);
934
        callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
935
    }
936

    
937
    /**
938
     * @deprecated Use {@link #getSpatialCache()}
939
     */
940
    public void clearSpatialCache() {
941
        spatialCache.clearAll();
942
    }
943

    
944
    /**
945
     * @deprecated Use {@link #getSpatialCache()}
946
     */
947
    public boolean isSpatialCacheEnabled() {
948
        return spatialCache.isEnabled();
949
    }
950

    
951
    /**
952
     * @deprecated Use {@link #getSpatialCache()}
953
     */
954
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
955
        spatialCache.setEnabled(spatialCacheEnabled);
956
    }
957

    
958
    public SpatialCache getSpatialCache() {
959
        return spatialCache;
960
    }
961

    
962
    /**
963
     * Siempre es un numero mayor de 1000
964
     * 
965
     * @param maxFeatures
966
     */
967
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
968
        if (maxFeatures > spatialCache.getMaxFeatures()) {
969
            spatialCache.setMaxFeatures(maxFeatures);
970
        }
971

    
972
    }
973

    
974
    /**
975
     * This method returns a boolean that is used by the FPopMenu
976
     * to make visible the properties menu or not. It is visible by
977
     * default, and if a later don't have to show this menu only
978
     * has to override this method.
979
     * 
980
     * @return
981
     *         If the properties menu is visible (or not)
982
     */
983
    public boolean isPropertiesMenuVisible() {
984
        return true;
985
    }
986

    
987
    public void reload() throws ReloadLayerException {
988
        super.reload();
989
        try {
990
            DataManager dataManager = DALLocator.getDataManager();
991
            DataStoreParameters storeParameters;
992

    
993
            storeParameters = getFeatureStore().getParameters();
994

    
995
            DataStore dataStore = dataManager.createStore(storeParameters);
996
            setDataStore(dataStore);
997
            getFeatureStore().refresh();
998
        } catch (Exception e) {
999
            throw new ReloadLayerException(getName(), e);
1000
        }
1001
        // try {
1002
        // this.source.getDriver().reload();
1003
        // if (this.getLegend() == null) {
1004
        // if (this.getRecordset().getDriver() instanceof WithDefaultLegend) {
1005
        // WithDefaultLegend aux = (WithDefaultLegend)
1006
        // this.getRecordset().getDriver();
1007
        // this.setLegend((IVectorLegend) aux.getDefaultLegend());
1008
        // this.setLabelingStrategy(aux.getDefaultLabelingStrategy());
1009
        // } else {
1010
        // this.setLegend(LegendFactory.createSingleSymbolLegend(
1011
        // this.getShapeType()));
1012
        // }
1013
        // }
1014
        //
1015
        // } catch (LegendLayerException e) {
1016
        // this.setAvailable(false);
1017
        // throw new ReloadLayerException(getName(),e);
1018
        // } catch (ReadException e) {
1019
        // this.setAvailable(false);
1020
        // throw new ReloadLayerException(getName(),e);
1021
        // }
1022

    
1023
    }
1024

    
1025
    protected void setLoadSelection(Object xml) {
1026
        // this.loadSelection = xml;
1027
    }
1028

    
1029
    protected void setLoadLegend(IVectorLegend legend) {
1030
        this.loadLegend = legend;
1031
    }
1032

    
1033
    protected void putLoadSelection() {
1034
        // if (this.loadSelection == null) return;
1035
        // try {
1036
        // this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
1037
        // } catch (ReadDriverException e) {
1038
        // throw new XMLException(e);
1039
        // }
1040
        // this.loadSelection = null;
1041

    
1042
    }
1043

    
1044
    protected void putLoadLegend() throws LegendLayerException {
1045
        if (this.loadLegend == null) {
1046
            return;
1047
        }
1048
        this.setLegend(this.loadLegend);
1049
        this.loadLegend = null;
1050
    }
1051

    
1052
    protected void cleanLoadOptions() {
1053
        this.loadLegend = null;
1054
    }
1055

    
1056
    public boolean isWritable() {
1057
        return getFeatureStore().allowWrite();
1058
    }
1059

    
1060
    public FLayer cloneLayer() throws Exception {
1061
        FLyrVect clonedLayer = new FLyrVect();
1062
        clonedLayer.setDataStore(getDataStore());
1063
        // if (isJoined()) {
1064
        // clonedLayer.setIsJoined(true);
1065
        // }
1066
        clonedLayer.setVisible(isVisible());
1067
        // clonedLayer.setISpatialIndex(getISpatialIndex());
1068
        clonedLayer.setName(getName());
1069
        clonedLayer.setCoordTrans(getCoordTrans());
1070

    
1071
        clonedLayer.setLegend((IVectorLegend) getLegend().cloneLegend());
1072

    
1073
        clonedLayer.setIsLabeled(isLabeled());
1074
        ILabelingStrategy labelingStrategy = getLabelingStrategy();
1075
        if (labelingStrategy != null) {
1076
            clonedLayer.setLabelingStrategy(labelingStrategy);
1077
        }
1078

    
1079
        return clonedLayer;
1080
    }
1081

    
1082
    protected boolean isOnePoint(AffineTransform graphicsTransform,
1083
        ViewPort viewPort,
1084
        double dpi,
1085
        CartographicSupport csSym,
1086
        Geometry geom,
1087
        int[] xyCoords) {
1088
        return isOnePoint(graphicsTransform, viewPort, geom, xyCoords)
1089
            && csSym.getCartographicSize(viewPort, dpi, geom) <= 1;
1090
    }
1091

    
1092
    private boolean isOnePoint(AffineTransform graphicsTransform,
1093
        ViewPort viewPort,
1094
        Geometry geom,
1095
        int[] xyCoords) {
1096
        boolean onePoint = false;
1097
        int type = geom.getType();
1098
        if (type == Geometry.TYPES.NULL) {
1099
            return false;
1100
        }
1101
        if (type != Geometry.TYPES.POINT && type != Geometry.TYPES.MULTIPOINT) {
1102

    
1103
            Envelope geomBounds = geom.getEnvelope();
1104

    
1105
            // ICoordTrans ct = getCoordTrans();
1106

    
1107
            // Se supone que la geometria ya esta reproyectada
1108
            // if (ct!=null) {
1109
            // // geomBounds = ct.getInverted().convert(geomBounds);
1110
            // geomBounds = geomBounds.convert(ct);
1111
            // }
1112

    
1113
            double dist1Pixel = viewPort.getDist1pixel();
1114

    
1115
            onePoint =
1116
                (geomBounds.getLength(0) <= dist1Pixel && geomBounds.getLength(1) <= dist1Pixel);
1117

    
1118
            if (onePoint) {
1119
                // avoid out of range exceptions
1120
                org.gvsig.fmap.geom.primitive.Point p;
1121
                try {
1122
                    p =
1123
                        geomManager.createPoint(geomBounds.getMinimum(0),
1124
                            geomBounds.getMinimum(1),
1125
                            SUBTYPES.GEOM2D);
1126
                    p.transform(viewPort.getAffineTransform());
1127
                    p.transform(graphicsTransform);
1128
                    xyCoords[0] = (int) p.getX();
1129
                    xyCoords[1] = (int) p.getY();
1130
                } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
1131
                    logger.error("Error creating a point", e);
1132
                }
1133

    
1134
            }
1135

    
1136
        }
1137
        return onePoint;
1138
    }
1139

    
1140
    /*
1141
     * jaume. Stuff from ILabeled.
1142
     */
1143

    
1144
    public boolean isLabeled() {
1145
        return isLabeled;
1146
    }
1147

    
1148
    public void setIsLabeled(boolean isLabeled) {
1149
        this.isLabeled = isLabeled;
1150
    }
1151

    
1152
    public ILabelingStrategy getLabelingStrategy() {
1153
        return strategy;
1154
    }
1155

    
1156
    public void setLabelingStrategy(ILabelingStrategy strategy) {
1157
        this.strategy = strategy;
1158
        if (strategy == null) {
1159
            return;
1160
        }
1161
        strategy.setLayer(this);
1162
    }
1163

    
1164
    public void drawLabels(BufferedImage image,
1165
        Graphics2D g,
1166
        ViewPort viewPort,
1167
        Cancellable cancel,
1168
        double scale,
1169
        double dpi) throws ReadException {
1170
        if (strategy != null && isWithinScale(scale)) {
1171
            strategy.draw(image, g, viewPort, cancel, dpi);
1172
        }
1173
    }
1174

    
1175
    public void printLabels(Graphics2D g,
1176
        ViewPort viewPort,
1177
        Cancellable cancel,
1178
        double scale,
1179
        PrintAttributes properties) throws ReadException {
1180
        if (strategy != null) {
1181
            strategy.print(g, viewPort, cancel, properties);
1182
        }
1183
    }
1184

    
1185
    // M?todos para el uso de HyperLinks en capas FLyerVect
1186

    
1187
    /**
1188
     * Return true, because a Vectorial Layer supports HyperLink
1189
     */
1190
    public boolean allowLinks() {
1191
        return true;
1192
    }
1193

    
1194
    /**
1195
     * Returns an instance of AbstractLinkProperties that contains the
1196
     * information
1197
     * of the HyperLink
1198
     * 
1199
     * @return Abstra
1200
     */
1201
    // public AbstractLinkProperties getLinkProperties()
1202
    // {
1203
    // return linkProperties;
1204
    // }
1205

    
1206
    /**
1207
     * Provides an array with URIs. Returns one URI by geometry that includes
1208
     * the point
1209
     * in its own geometry limits with a allowed tolerance.
1210
     * 
1211
     * @param layer
1212
     *            , the layer
1213
     * @param point
1214
     *            , the point to check that is contained or not in the
1215
     *            geometries in the layer
1216
     * @param tolerance
1217
     *            , the tolerance allowed. Allowed margin of error to detect if
1218
     *            the point
1219
     *            is contained in some geometries of the layer
1220
     * @return
1221
     * @throws ReadException
1222
     * @throws BehaviorException
1223
     */
1224
    // public URI[] getLink(Point2D point, double tolerance) throws
1225
    // ReadException
1226
    // {
1227
    // //return linkProperties.getLink(this)
1228
    // return linkProperties.getLink(this,point,tolerance);
1229
    // }
1230

    
1231
    public void load() throws LoadLayerException {
1232
        super.load();
1233
    }
1234

    
1235
    public FeatureStore getFeatureStore() {
1236
        return (FeatureStore) getDataStore();
1237
    }
1238

    
1239
    public FeatureSet queryByPoint(Point2D mapPoint,
1240
        double tol,
1241
        FeatureType featureType) throws DataException {
1242
        GeometryManager manager = GeometryLocator.getGeometryManager();
1243
        org.gvsig.fmap.geom.primitive.Point center;
1244
        try {
1245
            center =
1246
                (org.gvsig.fmap.geom.primitive.Point) manager.create(TYPES.POINT,
1247
                    SUBTYPES.GEOM2D);
1248
            center.setX(mapPoint.getX());
1249
            center.setY(mapPoint.getY());
1250
            Circle circle =
1251
                (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
1252
            circle.setPoints(center, tol);
1253
            return queryByGeometry(circle, featureType);
1254
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
1255
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
1256
        }
1257
    }
1258

    
1259
    public FeatureSet queryByGeometry(Geometry geom, FeatureType featureType) throws DataException {
1260
        FeatureQuery featureQuery = featureStore.createFeatureQuery();
1261
        String geomName =
1262
            featureStore.getDefaultFeatureType()
1263
                .getDefaultGeometryAttributeName();
1264
        featureQuery.setFeatureType(featureType);
1265
        IntersectsGeometryEvaluator iee =
1266
            new IntersectsGeometryEvaluator(geom,
1267
                getMapContext().getViewPort().getProjection(),
1268
                featureStore.getDefaultFeatureType(),
1269
                geomName);
1270
        featureQuery.setFilter(iee);
1271
        return getFeatureStore().getFeatureSet(featureQuery);
1272

    
1273
    }
1274

    
1275
    public FeatureSet queryByEnvelope(Envelope envelope, FeatureType featureType) throws DataException {
1276
        return queryByEnvelope(envelope, featureType, null);
1277
    }
1278

    
1279
    public FeatureSet queryByEnvelope(Envelope envelope,
1280
        FeatureType featureType,
1281
        String[] names) throws DataException {
1282
        FeatureQuery featureQuery = featureStore.createFeatureQuery();
1283
        if (names == null) {
1284
            featureQuery.setFeatureType(featureType);
1285
        } else {
1286
            featureQuery.setAttributeNames(names);
1287
            featureQuery.setFeatureTypeId(featureType.getId());
1288
        }
1289
        String geomName =
1290
            featureStore.getDefaultFeatureType()
1291
                .getDefaultGeometryAttributeName();
1292
        ContainsEnvelopeEvaluator iee =
1293
            new ContainsEnvelopeEvaluator(envelope,
1294
                getMapContext().getViewPort().getProjection(),
1295
                featureStore.getDefaultFeatureType(),
1296
                geomName);
1297
        featureQuery.setFilter(iee);
1298
        return getFeatureStore().getFeatureSet(featureQuery);
1299

    
1300
    }
1301

    
1302
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel) throws LoadLayerException,
1303
        DataException {
1304

    
1305
        return getInfo(p, tolerance, cancel, true);
1306
    }
1307

    
1308
    public DynObjectSet getInfo(Point p,
1309
        double tolerance,
1310
        Cancellable cancel,
1311
        boolean fast) throws LoadLayerException, DataException {
1312
        Point2D infop = new Point2D.Double(p.x, p.y);
1313
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(infop);
1314
        return queryByPoint(pReal,
1315
            tolerance,
1316
            getFeatureStore().getDefaultFeatureType()).getDynObjectSet(fast);
1317
    }
1318

    
1319
    public void legendCleared(LegendClearEvent event) {
1320
        // this.updateDrawVersion(); TODO
1321
        LegendChangedEvent e =
1322
            LegendChangedEvent.createLegendChangedEvent(legend, legend);
1323
        this.callLegendChanged(e);
1324
    }
1325

    
1326
    public boolean symbolChanged(SymbolLegendEvent e) {
1327
        LegendChangedEvent ev =
1328
            LegendChangedEvent.createLegendChangedEvent(legend, legend);
1329
        this.callLegendChanged(ev);
1330
        return true;
1331
    }
1332

    
1333
    public void update(Observable observable, Object notification) {
1334
        if (observable.equals(this.featureStore)) {
1335
            if (notification instanceof FeatureStoreNotification) {
1336
                FeatureStoreNotification event =
1337
                    (FeatureStoreNotification) notification;
1338
                if (event.getType() == FeatureStoreNotification.AFTER_CANCELEDITING
1339
                    || event.getType() == FeatureStoreNotification.AFTER_DELETE
1340
                    || event.getType() == FeatureStoreNotification.AFTER_UNDO
1341
                    || event.getType() == FeatureStoreNotification.AFTER_REDO
1342
                    || event.getType() == FeatureStoreNotification.AFTER_REFRESH
1343
                    || event.getType() == FeatureStoreNotification.AFTER_UPDATE
1344
                    || event.getType() == FeatureStoreNotification.AFTER_UPDATE_TYPE
1345
                    || event.getType() == FeatureStoreNotification.SELECTION_CHANGE
1346
                    || event.getType() == FeatureStoreNotification.AFTER_INSERT) {
1347
                    this.updateDrawVersion();
1348

    
1349
                } else if (event.getType() == FeatureStoreNotification.TRANSFORM_CHANGE){
1350
                    //If a transform has to be applied, try to reload the layer.
1351
                    try {
1352
                        reload();
1353
                    } catch (ReloadLayerException e) {
1354
                        this.setAvailable(false);
1355
                    }
1356
                } else if (event.getType() == FeatureStoreNotification.RESOURCE_CHANGED) {
1357
                    this.setAvailable(false);
1358
                } else         if (event.getType() == FeatureStoreNotification.AFTER_FINISHEDITING) {
1359
                    this.setAvailable(true);
1360
                }
1361
            }
1362
        }
1363
        // Only if its an event from our own legend
1364
        else
1365
            // I comment this line because a legend doesn't implements the
1366
            // Observable interface.
1367
            // This code is necessary on edition.
1368
            // if (observable == getLegend()) {
1369
            if (notification instanceof FeatureDrawnNotification) {
1370
                Geometry geometry =
1371
                    ((FeatureDrawnNotification) notification).getDrawnGeometry();
1372
                spatialCache.insert(geometry.getEnvelope(), geometry);
1373
                // }
1374
            }
1375

    
1376
    }
1377

    
1378
    /*
1379
     * (non-Javadoc)
1380
     * 
1381
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1382
     */
1383
    public Set getMetadataChildren() {
1384
        Set ret = new TreeSet();
1385
        ret.add(this.featureStore);
1386
        return ret;
1387
    }
1388

    
1389
    /*
1390
     * (non-Javadoc)
1391
     * 
1392
     * @see org.gvsig.metadata.Metadata#getMetadataID()
1393
     */
1394
    public Object getMetadataID() throws MetadataException {
1395
        return "Layer(" + this.getName() + "):"
1396
            + this.featureStore.getMetadataID();
1397
    }
1398

    
1399
    
1400

    
1401
    public GeometryType getTypeVectorLayer() throws DataException,
1402
        LocatorException,
1403
        GeometryTypeNotSupportedException,
1404
        GeometryTypeNotValidException {
1405
        // FIXME Esto deberia de pedirse a FType!!!!
1406
        FeatureStore fs = this.getFeatureStore();
1407
        FeatureType fType = fs.getDefaultFeatureType();
1408
        FeatureAttributeDescriptor attr =
1409
            fType.getAttributeDescriptor(fType.getDefaultGeometryAttributeIndex());
1410
        GeometryType geomType =
1411
            GeometryLocator.getGeometryManager()
1412
                .getGeometryType(attr.getGeometryType(),
1413
                    attr.getGeometrySubType());
1414
        return geomType;
1415
    }
1416

    
1417
    public static void registerPersistent() {
1418
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1419
        if (manager.getDefinition(FLyrDefault.class) == null) {
1420
            FLyrDefault.registerPersistent();
1421
        }
1422
        DynStruct definition =
1423
            manager.addDefinition(FLyrVect.class,
1424
                "FLyrVect",
1425
                "FLyrVect Persistence definition",
1426
                null,
1427
                null);
1428
        definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE,
1429
            "FLyrDefault");
1430

    
1431
        definition.addDynFieldObject("legend")
1432
            .setClassOfValue(IVectorLegend.class)
1433
            .setMandatory(true);
1434
        definition.addDynFieldObject("featureStore")
1435
            .setClassOfValue(FeatureStore.class)
1436
            .setMandatory(true);
1437
        definition.addDynFieldBoolean("isLabeled").setMandatory(true);
1438
        definition.addDynFieldInt("typeShape").setMandatory(true);
1439
        definition.addDynFieldObject("labelingStrategy")
1440
            .setClassOfValue(ILabelingStrategy.class)
1441
            .setMandatory(false);
1442

    
1443
    }
1444

    
1445
    protected void doDispose() throws BaseException {
1446
        dispose(featureStore);
1447
        spatialCache.clearAll();
1448
    }
1449
}