Statistics
| Revision:

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

History | View | Annotate | Download (50.6 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.persistence.exception.PersistenceRuntimeException;
115
import org.gvsig.tools.task.Cancellable;
116

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

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

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

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

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

    
143
    private boolean isLabeled;
144
    protected ILabelingStrategy strategy;
145

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

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

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

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

    
267
        featureStore = (FeatureStore) dataStore;
268

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

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

    
276
        this.setLegend(legend);
277

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

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

    
298
        this.delegate(dataStore);
299

    
300
        dataStore.addObserver(this);
301

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

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

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

    
353
    }
354

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
586
    public void saveToState(PersistentState state) throws PersistenceException {
587

    
588
        if (!this.isAvailable()) {
589
            return;
590
        }
591

    
592
        super.saveToState(state);
593

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

    
598
        FeatureStore fst = null;
599
        fst = getFeatureStore();
600

    
601
        if (fst != null) {
602
            state.set("featureStore", fst);
603
        }
604

    
605
        state.set("isLabeled", isLabeled);
606

    
607
        if (strategy != null) {
608
            state.set("labelingStrategy", strategy);
609
        }
610

    
611
        if (getLinkProperties() != null) {
612
            state.set("linkProperties", getLinkProperties());
613
        }
614

    
615
        // state.set("bHasJoin", bHasJoin);
616
        state.set("typeShape", typeShape);
617
    }
618

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

    
651
    public void loadFromState(PersistentState state) throws PersistenceException {
652

    
653
        super.loadFromState(state);
654
        DataStore store = null;
655
        try {
656
                store = (DataStore) state.get("featureStore");
657
        } catch (PersistenceRuntimeException e) {
658
                        this.setAvailable(false);
659
                        return;
660
                }
661
        try {
662
            this.setDataStore(store);
663
        } catch (LoadLayerException e) {
664
            throw new PersistenceException("While loading FLyrVect from state.",
665
                e);
666
        }
667

    
668
        IVectorLegend lgnd = (IVectorLegend) state.get("legend");
669
        try {
670
            this.setLegend(lgnd);
671
        } catch (LegendLayerException e) {
672
            throw new PersistenceException("While loading FLyrVect from state.",
673
                e);
674
        }
675

    
676
        Boolean isLbl = new Boolean(false);
677
        ILabelingStrategy lblst = null;
678

    
679
        try {
680
            isLbl = (Boolean) state.get("isLabeled");
681
            if (isLbl.booleanValue()) {
682
                lblst = (ILabelingStrategy) state.get("labelingStrategy");
683
            }
684
        } catch (Exception ex) {
685
            throw new PersistenceException("While loading FLyrVect from state.",
686
                ex);
687
        }
688

    
689
        /*
690
         * String _labelFieldName = null;
691
         * String _labelfield = null;
692
         */
693

    
694
        if (isLbl.booleanValue()) {
695
            this.setIsLabeled(true);
696
            this.setLabelingStrategy(lblst);
697
        } else {
698
            this.setIsLabeled(false);
699
            this.setLabelingStrategy(null);
700
        }
701

    
702
        // try {
703
        // linkProperties = (FLyrVectLinkProperties)
704
        // state.get("linkProperties");
705
        // } catch (PersistenceException pex) {
706
        // // not mandatory
707
        // linkProperties = null;
708
        // }
709

    
710
        // bHasJoin = state.getBoolean("bHasJoin");
711
        typeShape = state.getInt("typeShape");
712

    
713
        // try { _labelFieldName = state.getString("labelFieldName"); } catch
714
        // (PersistenceException ex) {
715
        // _labelFieldName = null;
716
        // }
717
        // try { _labelfield = state.getString("labelfield"); } catch
718
        // (PersistenceException ex) {
719
        // _labelfield = null;
720
        // }
721

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

    
762
    }
763

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

    
857
    /**
858
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
859
     * identifiquen la capa.
860
     * 
861
     * @return DOCUMENT ME!
862
     */
863
    public String toString() {
864
        /*
865
         * Se usa internamente para que la parte de datos identifique de forma
866
         * un?voca las tablas
867
         */
868
        String ret = super.toString();
869

    
870
        return "layer" + ret.substring(ret.indexOf('@') + 1);
871
    }
872

    
873
    // public boolean isJoined() {
874
    // return bHasJoin;
875
    // }
876

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

    
914
    // /**
915
    // * @return Returns the spatialIndex.
916
    // */
917
    // public ISpatialIndex getISpatialIndex() {
918
    // return spatialIndex;
919
    // }
920
    // /**
921
    // * Sets the spatial index. This could be useful if, for some
922
    // * reasons, you want to work with a distinct spatial index
923
    // * (for example, a spatial index which could makes nearest
924
    // * neighbour querys)
925
    // * @param spatialIndex
926
    // */
927
    // public void setISpatialIndex(ISpatialIndex spatialIndex){
928
    // this.spatialIndex = spatialIndex;
929
    // }
930

    
931
    public void setEditing(boolean b) throws StartEditionLayerException {
932
        super.setEditing(b);
933
        FeatureStore fs = getFeatureStore();
934
        if (b) {
935
            try {
936
                fs.edit();
937
            } catch (ReadException e) {
938
                throw new StartEditionLayerException(getName(), e);
939
            } catch (DataException e) {
940
                throw new StartEditionLayerException(getName(), e);
941
            }
942
        }
943
        setSpatialCacheEnabled(b);
944
        callEditionChanged(LayerEvent.createEditionChangedEvent(this, "edition"));
945
    }
946

    
947
    /**
948
     * @deprecated Use {@link #getSpatialCache()}
949
     */
950
    public void clearSpatialCache() {
951
        spatialCache.clearAll();
952
    }
953

    
954
    /**
955
     * @deprecated Use {@link #getSpatialCache()}
956
     */
957
    public boolean isSpatialCacheEnabled() {
958
        return spatialCache.isEnabled();
959
    }
960

    
961
    /**
962
     * @deprecated Use {@link #getSpatialCache()}
963
     */
964
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
965
        spatialCache.setEnabled(spatialCacheEnabled);
966
    }
967

    
968
    public SpatialCache getSpatialCache() {
969
        return spatialCache;
970
    }
971

    
972
    /**
973
     * Siempre es un numero mayor de 1000
974
     * 
975
     * @param maxFeatures
976
     */
977
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
978
        if (maxFeatures > spatialCache.getMaxFeatures()) {
979
            spatialCache.setMaxFeatures(maxFeatures);
980
        }
981

    
982
    }
983

    
984
    /**
985
     * This method returns a boolean that is used by the FPopMenu
986
     * to make visible the properties menu or not. It is visible by
987
     * default, and if a later don't have to show this menu only
988
     * has to override this method.
989
     * 
990
     * @return
991
     *         If the properties menu is visible (or not)
992
     */
993
    public boolean isPropertiesMenuVisible() {
994
        return true;
995
    }
996

    
997
    public void reload() throws ReloadLayerException {
998
        super.reload();
999
        try {
1000
            getFeatureStore().refresh();
1001
        } catch (Exception e) {
1002
            throw new ReloadLayerException(getName(), e);
1003
        }
1004
    }
1005

    
1006
    protected void setLoadSelection(Object xml) {
1007
        // this.loadSelection = xml;
1008
    }
1009

    
1010
    protected void setLoadLegend(IVectorLegend legend) {
1011
        this.loadLegend = legend;
1012
    }
1013

    
1014
    protected void putLoadSelection() {
1015
        // if (this.loadSelection == null) return;
1016
        // try {
1017
        // this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
1018
        // } catch (ReadDriverException e) {
1019
        // throw new XMLException(e);
1020
        // }
1021
        // this.loadSelection = null;
1022

    
1023
    }
1024

    
1025
    protected void putLoadLegend() throws LegendLayerException {
1026
        if (this.loadLegend == null) {
1027
            return;
1028
        }
1029
        this.setLegend(this.loadLegend);
1030
        this.loadLegend = null;
1031
    }
1032

    
1033
    protected void cleanLoadOptions() {
1034
        this.loadLegend = null;
1035
    }
1036

    
1037
    public boolean isWritable() {
1038
        return getFeatureStore().allowWrite();
1039
    }
1040

    
1041
    public FLayer cloneLayer() throws Exception {
1042
        FLyrVect clonedLayer = new FLyrVect();
1043
        clonedLayer.setDataStore(getDataStore());
1044
        // if (isJoined()) {
1045
        // clonedLayer.setIsJoined(true);
1046
        // }
1047
        clonedLayer.setVisible(isVisible());
1048
        // clonedLayer.setISpatialIndex(getISpatialIndex());
1049
        clonedLayer.setName(getName());
1050
        clonedLayer.setCoordTrans(getCoordTrans());
1051

    
1052
        clonedLayer.setLegend((IVectorLegend) getLegend().cloneLegend());
1053

    
1054
        clonedLayer.setIsLabeled(isLabeled());
1055
        ILabelingStrategy labelingStrategy = getLabelingStrategy();
1056
        if (labelingStrategy != null) {
1057
            clonedLayer.setLabelingStrategy(labelingStrategy);
1058
        }
1059

    
1060
        return clonedLayer;
1061
    }
1062

    
1063
    protected boolean isOnePoint(AffineTransform graphicsTransform,
1064
        ViewPort viewPort,
1065
        double dpi,
1066
        CartographicSupport csSym,
1067
        Geometry geom,
1068
        int[] xyCoords) {
1069
        return isOnePoint(graphicsTransform, viewPort, geom, xyCoords)
1070
            && csSym.getCartographicSize(viewPort, dpi, geom) <= 1;
1071
    }
1072

    
1073
    private boolean isOnePoint(AffineTransform graphicsTransform,
1074
        ViewPort viewPort,
1075
        Geometry geom,
1076
        int[] xyCoords) {
1077
        boolean onePoint = false;
1078
        int type = geom.getType();
1079
        if (type == Geometry.TYPES.NULL) {
1080
            return false;
1081
        }
1082
        if (type != Geometry.TYPES.POINT && type != Geometry.TYPES.MULTIPOINT) {
1083

    
1084
            Envelope geomBounds = geom.getEnvelope();
1085

    
1086
            // ICoordTrans ct = getCoordTrans();
1087

    
1088
            // Se supone que la geometria ya esta reproyectada
1089
            // if (ct!=null) {
1090
            // // geomBounds = ct.getInverted().convert(geomBounds);
1091
            // geomBounds = geomBounds.convert(ct);
1092
            // }
1093

    
1094
            double dist1Pixel = viewPort.getDist1pixel();
1095

    
1096
            onePoint =
1097
                (geomBounds.getLength(0) <= dist1Pixel && geomBounds.getLength(1) <= dist1Pixel);
1098

    
1099
            if (onePoint) {
1100
                // avoid out of range exceptions
1101
                org.gvsig.fmap.geom.primitive.Point p;
1102
                try {
1103
                    p =
1104
                        geomManager.createPoint(geomBounds.getMinimum(0),
1105
                            geomBounds.getMinimum(1),
1106
                            SUBTYPES.GEOM2D);
1107
                    p.transform(viewPort.getAffineTransform());
1108
                    p.transform(graphicsTransform);
1109
                    xyCoords[0] = (int) p.getX();
1110
                    xyCoords[1] = (int) p.getY();
1111
                } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
1112
                    logger.error("Error creating a point", e);
1113
                }
1114

    
1115
            }
1116

    
1117
        }
1118
        return onePoint;
1119
    }
1120

    
1121
    /*
1122
     * jaume. Stuff from ILabeled.
1123
     */
1124

    
1125
    public boolean isLabeled() {
1126
        return isLabeled;
1127
    }
1128

    
1129
    public void setIsLabeled(boolean isLabeled) {
1130
        this.isLabeled = isLabeled;
1131
    }
1132

    
1133
    public ILabelingStrategy getLabelingStrategy() {
1134
        return strategy;
1135
    }
1136

    
1137
    public void setLabelingStrategy(ILabelingStrategy strategy) {
1138
        this.strategy = strategy;
1139
        if (strategy == null) {
1140
            return;
1141
        }
1142
        strategy.setLayer(this);
1143
    }
1144

    
1145
    public void drawLabels(BufferedImage image,
1146
        Graphics2D g,
1147
        ViewPort viewPort,
1148
        Cancellable cancel,
1149
        double scale,
1150
        double dpi) throws ReadException {
1151
        if (strategy != null && isWithinScale(scale)) {
1152
            strategy.draw(image, g, viewPort, cancel, dpi);
1153
        }
1154
    }
1155

    
1156
    public void printLabels(Graphics2D g,
1157
        ViewPort viewPort,
1158
        Cancellable cancel,
1159
        double scale,
1160
        PrintAttributes properties) throws ReadException {
1161
        if (strategy != null) {
1162
            strategy.print(g, viewPort, cancel, properties);
1163
        }
1164
    }
1165

    
1166
    // M?todos para el uso de HyperLinks en capas FLyerVect
1167

    
1168
    /**
1169
     * Return true, because a Vectorial Layer supports HyperLink
1170
     */
1171
    public boolean allowLinks() {
1172
        return true;
1173
    }
1174

    
1175
    /**
1176
     * Returns an instance of AbstractLinkProperties that contains the
1177
     * information
1178
     * of the HyperLink
1179
     * 
1180
     * @return Abstra
1181
     */
1182
    // public AbstractLinkProperties getLinkProperties()
1183
    // {
1184
    // return linkProperties;
1185
    // }
1186

    
1187
    /**
1188
     * Provides an array with URIs. Returns one URI by geometry that includes
1189
     * the point
1190
     * in its own geometry limits with a allowed tolerance.
1191
     * 
1192
     * @param layer
1193
     *            , the layer
1194
     * @param point
1195
     *            , the point to check that is contained or not in the
1196
     *            geometries in the layer
1197
     * @param tolerance
1198
     *            , the tolerance allowed. Allowed margin of error to detect if
1199
     *            the point
1200
     *            is contained in some geometries of the layer
1201
     * @return
1202
     * @throws ReadException
1203
     * @throws BehaviorException
1204
     */
1205
    // public URI[] getLink(Point2D point, double tolerance) throws
1206
    // ReadException
1207
    // {
1208
    // //return linkProperties.getLink(this)
1209
    // return linkProperties.getLink(this,point,tolerance);
1210
    // }
1211

    
1212
    public void load() throws LoadLayerException {
1213
        super.load();
1214
    }
1215

    
1216
    public FeatureStore getFeatureStore() {
1217
        return (FeatureStore) getDataStore();
1218
    }
1219

    
1220
    /**
1221
     * @deprecated use instead {@link #queryByPoint(org.gvsig.fmap.geom.primitive.Point, double, FeatureType)}
1222
     */
1223
    public FeatureSet queryByPoint(Point2D mapPoint,
1224
        double tol,
1225
        FeatureType featureType) throws DataException {
1226
        logger.warn("Deprecated use of queryByPoint.");
1227
        GeometryManager manager = GeometryLocator.getGeometryManager();
1228
        org.gvsig.fmap.geom.primitive.Point center;
1229
        try {
1230
            center =
1231
                (org.gvsig.fmap.geom.primitive.Point) manager.create(TYPES.POINT,
1232
                    SUBTYPES.GEOM2D);
1233
            center.setX(mapPoint.getX());
1234
            center.setY(mapPoint.getY());
1235
            Circle circle =
1236
                (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
1237
            circle.setPoints(center, tol);
1238
            return queryByGeometry(circle, featureType);
1239
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
1240
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
1241
        }
1242
    }
1243

    
1244
    public FeatureSet queryByPoint(org.gvsig.fmap.geom.primitive.Point point,
1245
        double tol,
1246
        FeatureType featureType) throws DataException {
1247
        GeometryManager manager = GeometryLocator.getGeometryManager();
1248
        try {
1249
            Circle circle =
1250
                (Circle) manager.create(TYPES.CIRCLE, SUBTYPES.GEOM2D);
1251
            circle.setPoints(point, tol);
1252
            return queryByGeometry(circle, featureType);
1253
        } catch (org.gvsig.fmap.geom.exception.CreateGeometryException e) {
1254
            throw new CreateGeometryException(TYPES.CIRCLE, SUBTYPES.GEOM2D, e);
1255
        }
1256
    }
1257

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

    
1272
    }
1273

    
1274
    /**
1275
     * It return the {@link FeatureSet} that intersects with the envelope.
1276
     * @param envelope
1277
     *          envelope that defines the area for the query.
1278
     * @param featureType
1279
     *          only the features with this feature type are used in
1280
     *          the query.    
1281
     * @return
1282
     *          the set of features that intersect with the envelope.
1283
     * @throws DataException
1284
     */
1285
    public FeatureSet queryByEnvelope(Envelope envelope, FeatureType featureType) throws DataException {
1286
        return queryByEnvelope(envelope, featureType, null);
1287
    }
1288

    
1289
    /**
1290
     * It return the {@link FeatureSet} that intersects with the envelope.
1291
     * @param envelope
1292
     *          envelope that defines the area for the query.
1293
     * @param featureType
1294
     *          only the features with this feature type are used in
1295
     *          the query.
1296
     * @param names
1297
     *          the feature attributes that have to be checked.
1298
     * @return
1299
     *          the set of features that intersect with the envelope.
1300
     * @throws DataException
1301
     */
1302
    public FeatureSet queryByEnvelope(Envelope envelope,
1303
        FeatureType featureType,
1304
        String[] names) throws DataException {
1305
        FeatureQuery featureQuery = featureStore.createFeatureQuery();
1306
        if (names == null) {
1307
            featureQuery.setFeatureType(featureType);
1308
        } else {
1309
            featureQuery.setAttributeNames(names);
1310
            featureQuery.setFeatureTypeId(featureType.getId());
1311
        }
1312
        String geomName =
1313
            featureStore.getDefaultFeatureType()
1314
                .getDefaultGeometryAttributeName();
1315
        IntersectsGeometryEvaluator iee =
1316
            new IntersectsGeometryEvaluator(envelope.getGeometry(),
1317
                getMapContext().getViewPort().getProjection(),
1318
                featureStore.getDefaultFeatureType(),
1319
                geomName);
1320
        featureQuery.setFilter(iee);
1321
        return getFeatureStore().getFeatureSet(featureQuery);
1322

    
1323
    }
1324

    
1325
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel) throws LoadLayerException,
1326
        DataException {
1327

    
1328
        return getInfo(p, tolerance, cancel, true);
1329
    }
1330

    
1331
    public DynObjectSet getInfo(Point p,
1332
        double tolerance,
1333
        Cancellable cancel,
1334
        boolean fast) throws LoadLayerException, DataException {
1335
        Point2D infop = new Point2D.Double(p.x, p.y);
1336
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(infop);
1337
        return queryByPoint(pReal,
1338
            tolerance,
1339
            getFeatureStore().getDefaultFeatureType()).getDynObjectSet(fast);
1340
    }
1341

    
1342
    public DynObjectSet getInfo(org.gvsig.fmap.geom.primitive.Point p,
1343
        double tolerance) throws LoadLayerException, DataException {
1344
        return queryByPoint(p,tolerance, getFeatureStore().getDefaultFeatureType()).getDynObjectSet(false);
1345
    }
1346
    
1347
    public void legendCleared(LegendClearEvent event) {
1348
        // this.updateDrawVersion(); TODO
1349
        LegendChangedEvent e =
1350
            LegendChangedEvent.createLegendChangedEvent(legend, legend);
1351
        this.callLegendChanged(e);
1352
    }
1353

    
1354
    public boolean symbolChanged(SymbolLegendEvent e) {
1355
        LegendChangedEvent ev =
1356
            LegendChangedEvent.createLegendChangedEvent(legend, legend);
1357
        this.callLegendChanged(ev);
1358
        return true;
1359
    }
1360

    
1361
    public void update(Observable observable, Object notification) {
1362
        if (observable.equals(this.featureStore)) {
1363
            if (notification instanceof FeatureStoreNotification) {
1364
                FeatureStoreNotification event =
1365
                    (FeatureStoreNotification) notification;
1366
                if (event.getType() == FeatureStoreNotification.AFTER_CANCELEDITING
1367
                    || event.getType() == FeatureStoreNotification.AFTER_DELETE
1368
                    || event.getType() == FeatureStoreNotification.AFTER_UNDO
1369
                    || event.getType() == FeatureStoreNotification.AFTER_REDO
1370
                    || event.getType() == FeatureStoreNotification.AFTER_REFRESH
1371
                    || event.getType() == FeatureStoreNotification.AFTER_UPDATE
1372
                    || event.getType() == FeatureStoreNotification.AFTER_UPDATE_TYPE
1373
                    || event.getType() == FeatureStoreNotification.SELECTION_CHANGE
1374
                    || event.getType() == FeatureStoreNotification.AFTER_INSERT) {
1375
                    this.updateDrawVersion();
1376

    
1377
                } else if (event.getType() == FeatureStoreNotification.TRANSFORM_CHANGE){
1378
                    //If a transform has to be applied, try to reload the layer.
1379
                    try {
1380
                        reload();
1381
                    } catch (ReloadLayerException e) {
1382
                        this.setAvailable(false);
1383
                    }
1384
                } else if (event.getType() == FeatureStoreNotification.RESOURCE_CHANGED) {
1385
                    this.setAvailable(false);
1386
                } else         if (event.getType() == FeatureStoreNotification.AFTER_FINISHEDITING) {
1387
                    this.setAvailable(true);
1388
                }
1389
            }
1390
        }
1391
        // Only if its an event from our own legend
1392
        else
1393
            // I comment this line because a legend doesn't implements the
1394
            // Observable interface.
1395
            // This code is necessary on edition.
1396
            // if (observable == getLegend()) {
1397
            if (notification instanceof FeatureDrawnNotification) {
1398
                Geometry geometry =
1399
                    ((FeatureDrawnNotification) notification).getDrawnGeometry();
1400
                spatialCache.insert(geometry.getEnvelope(), geometry);
1401
                // }
1402
            }
1403

    
1404
    }
1405

    
1406
    /*
1407
     * (non-Javadoc)
1408
     * 
1409
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1410
     */
1411
    public Set getMetadataChildren() {
1412
        Set ret = new TreeSet();
1413
        ret.add(this.featureStore);
1414
        return ret;
1415
    }
1416

    
1417
    /*
1418
     * (non-Javadoc)
1419
     * 
1420
     * @see org.gvsig.metadata.Metadata#getMetadataID()
1421
     */
1422
    public Object getMetadataID() throws MetadataException {
1423
        return "Layer(" + this.getName() + "):"
1424
            + this.featureStore.getMetadataID();
1425
    }
1426

    
1427
    
1428

    
1429
    public GeometryType getTypeVectorLayer() throws DataException,
1430
        LocatorException,
1431
        GeometryTypeNotSupportedException,
1432
        GeometryTypeNotValidException {
1433
        // FIXME Esto deberia de pedirse a FType!!!!
1434
        FeatureStore fs = this.getFeatureStore();
1435
        FeatureType fType = fs.getDefaultFeatureType();
1436
        FeatureAttributeDescriptor attr =
1437
            fType.getAttributeDescriptor(fType.getDefaultGeometryAttributeIndex());
1438
        GeometryType geomType =
1439
            GeometryLocator.getGeometryManager()
1440
                .getGeometryType(attr.getGeometryType(),
1441
                    attr.getGeometrySubType());
1442
        return geomType;
1443
    }
1444

    
1445
    public static void registerPersistent() {
1446
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1447
        if (manager.getDefinition(FLyrDefault.class) == null) {
1448
            FLyrDefault.registerPersistent();
1449
        }
1450
        DynStruct definition =
1451
            manager.addDefinition(FLyrVect.class,
1452
                "FLyrVect",
1453
                "FLyrVect Persistence definition",
1454
                null,
1455
                null);
1456
        definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE,
1457
            "FLyrDefault");
1458

    
1459
        definition.addDynFieldObject("legend")
1460
            .setClassOfValue(IVectorLegend.class)
1461
            .setMandatory(true);
1462
        definition.addDynFieldObject("featureStore")
1463
            .setClassOfValue(FeatureStore.class)
1464
            .setMandatory(true);
1465
        definition.addDynFieldBoolean("isLabeled").setMandatory(true);
1466
        definition.addDynFieldInt("typeShape").setMandatory(true);
1467
        definition.addDynFieldObject("labelingStrategy")
1468
            .setClassOfValue(ILabelingStrategy.class)
1469
            .setMandatory(false);
1470

    
1471
    }
1472

    
1473
    protected void doDispose() throws BaseException {
1474
        dispose(featureStore);
1475
        spatialCache.clearAll();
1476
    }
1477
}