Statistics
| Revision:

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

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

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

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

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

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

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

    
520
    // public void createSpatialIndex() {
521
    // createSpatialIndex(null);
522
    // }
523

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

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

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

    
579
    public void saveToState(PersistentState state) throws PersistenceException {
580

    
581
        if (!this.isAvailable()) {
582
            return;
583
        }
584

    
585
        super.saveToState(state);
586

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

    
591
        FeatureStore fst = null;
592
        fst = getFeatureStore();
593

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

    
598
        state.set("isLabeled", isLabeled);
599

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

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

    
608
        // state.set("bHasJoin", bHasJoin);
609
        state.set("typeShape", typeShape);
610
    }
611

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

    
644
    public void loadFromState(PersistentState state) throws PersistenceException {
645

    
646
        super.loadFromState(state);
647

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

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

    
664
        Boolean isLbl = new Boolean(false);
665
        ILabelingStrategy lblst = null;
666

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

    
677
        /*
678
         * String _labelFieldName = null;
679
         * String _labelfield = null;
680
         */
681

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

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

    
698
        // bHasJoin = state.getBoolean("bHasJoin");
699
        typeShape = state.getInt("typeShape");
700

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

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

    
750
    }
751

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

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

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

    
861
    // public boolean isJoined() {
862
    // return bHasJoin;
863
    // }
864

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

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

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

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

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

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

    
956
    public SpatialCache getSpatialCache() {
957
        return spatialCache;
958
    }
959

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

    
970
    }
971

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

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

    
991
            storeParameters = getFeatureStore().getParameters();
992

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

    
1021
    }
1022

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

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

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

    
1040
    }
1041

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

    
1050
    protected void cleanLoadOptions() {
1051
        this.loadLegend = null;
1052
    }
1053

    
1054
    public boolean isWritable() {
1055
        return getFeatureStore().allowWrite();
1056
    }
1057

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

    
1069
        clonedLayer.setLegend((IVectorLegend) getLegend().cloneLegend());
1070

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

    
1077
        return clonedLayer;
1078
    }
1079

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

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

    
1101
            Envelope geomBounds = geom.getEnvelope();
1102

    
1103
            // ICoordTrans ct = getCoordTrans();
1104

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

    
1111
            double dist1Pixel = viewPort.getDist1pixel();
1112

    
1113
            onePoint =
1114
                (geomBounds.getLength(0) <= dist1Pixel && geomBounds.getLength(1) <= dist1Pixel);
1115

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

    
1132
            }
1133

    
1134
        }
1135
        return onePoint;
1136
    }
1137

    
1138
    /*
1139
     * jaume. Stuff from ILabeled.
1140
     */
1141

    
1142
    public boolean isLabeled() {
1143
        return isLabeled;
1144
    }
1145

    
1146
    public void setIsLabeled(boolean isLabeled) {
1147
        this.isLabeled = isLabeled;
1148
    }
1149

    
1150
    public ILabelingStrategy getLabelingStrategy() {
1151
        return strategy;
1152
    }
1153

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

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

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

    
1183
    // M?todos para el uso de HyperLinks en capas FLyerVect
1184

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

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

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

    
1229
    public void load() throws LoadLayerException {
1230
        super.load();
1231
    }
1232

    
1233
    public FeatureStore getFeatureStore() {
1234
        return (FeatureStore) getDataStore();
1235
    }
1236

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

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

    
1271
    }
1272

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

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

    
1298
    }
1299

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

    
1303
        return getInfo(p, tolerance, cancel, true);
1304
    }
1305

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

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

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

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

    
1347
                } else
1348
                    if (event.getType() == FeatureStoreNotification.TRANSFORM_CHANGE
1349
                        || event.getType() == FeatureStoreNotification.RESOURCE_CHANGED) {
1350
                        this.setAvailable(false);
1351

    
1352
//                         try {
1353
//                         reload();
1354
//                         } catch (ReloadLayerException e) {
1355
//                         this.setAvailable(false);
1356
//                         }
1357

    
1358
                    } else
1359
                            if (event.getType() == FeatureStoreNotification.AFTER_FINISHEDITING) {
1360
                            this.setAvailable(true);
1361
                            }
1362
            }
1363

    
1364
        }
1365
        // Only if its an event from our own legend
1366
        else
1367
            // I comment this line because a legend doesn't implements the
1368
            // Observable interface.
1369
            // This code is necessary on edition.
1370
            // if (observable == getLegend()) {
1371
            if (notification instanceof FeatureDrawnNotification) {
1372
                Geometry geometry =
1373
                    ((FeatureDrawnNotification) notification).getDrawnGeometry();
1374
                spatialCache.insert(geometry.getEnvelope(), geometry);
1375
                // }
1376
            }
1377

    
1378
    }
1379

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

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

    
1401
    
1402

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

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

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

    
1445
    }
1446

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