Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.app / org.gvsig.app.mainplugin / src / main / java / org / gvsig / app / project / symboltables / ProjectSymbolTable.java @ 44129

History | View | Annotate | Download (20.6 KB)

1
package org.gvsig.app.project.symboltables;
2

    
3
import java.io.File;
4
import java.io.FileInputStream;
5
import java.util.HashMap;
6
import java.util.Iterator;
7
import java.util.Map;
8
import java.util.Properties;
9
import org.apache.commons.io.IOUtils;
10
import org.apache.commons.lang3.Range;
11
import org.cresques.cts.IProjection;
12
import org.gvsig.app.ApplicationLocator;
13
import org.gvsig.app.ApplicationManager;
14
import org.gvsig.app.project.Project;
15
import org.gvsig.app.project.ProjectManager;
16
import org.gvsig.app.project.documents.Document;
17
import org.gvsig.app.project.documents.view.ViewDocument;
18
import org.gvsig.app.project.documents.view.ViewManager;
19
import org.gvsig.expressionevaluator.Interpreter;
20
import org.gvsig.expressionevaluator.spi.AbstractFunction;
21
import org.gvsig.expressionevaluator.spi.AbstractSymbolTable;
22
import org.gvsig.fmap.crs.CRSFactory;
23
import org.gvsig.fmap.dal.feature.Feature;
24
import org.gvsig.fmap.dal.feature.FeatureQuery;
25
import org.gvsig.fmap.dal.feature.FeatureSelection;
26
import org.gvsig.fmap.dal.feature.FeatureSet;
27
import org.gvsig.fmap.dal.feature.FeatureStore;
28
import org.gvsig.fmap.geom.Geometry;
29
import org.gvsig.fmap.geom.primitive.Point;
30
import org.gvsig.fmap.mapcontext.MapContext;
31
import org.gvsig.fmap.mapcontext.layers.FLayer;
32
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
33
import org.gvsig.fmap.mapcontrol.AreaAndPerimeterCalculator;
34
import org.gvsig.temporarystorage.TemporaryStorageGroup;
35
import org.gvsig.temporarystorage.TemporaryStorageLocator;
36
import org.gvsig.temporarystorage.TemporaryStorageManager;
37

    
38
/**
39
 *
40
 * @author jjdelcerro
41
 */
42
@SuppressWarnings("UseSpecificCatch")
43
public class ProjectSymbolTable extends AbstractSymbolTable {
44

    
45
    public static final String AREA_NAME = "AREA";        
46
    public static final String PERIMETER_NAME = "PERIMETER";
47
    public static final String FIRSTLAYERFEATURE_NAME = "FirstLayerFeature";
48
        
49
    static final String NAME = "Project";
50
    
51
    private abstract class CachedValue<T> {
52

    
53
        T value = null;
54
        long lastAccess = 0;
55

    
56
        protected abstract void reload();
57

    
58
        public boolean isExpired() {
59
            long now = System.currentTimeMillis();
60
            return now - lastAccess > 3000;
61
        }
62

    
63
        public T get() {
64
            if (isExpired()) {
65
                reload();
66
            }
67
            lastAccess = System.currentTimeMillis();
68
            return value;
69
        }
70
    }
71

    
72
    private class ProjectValue extends CachedValue<Project> {
73

    
74
        @Override
75
        protected void reload() {
76
            value = ProjectManager.getInstance().getCurrentProject();
77
        }
78

    
79
    }
80

    
81
    private class CurrentViewValue extends CachedValue<ViewDocument> {
82

    
83
        @Override
84
        protected void reload() {
85
            ApplicationManager application = ApplicationLocator.getManager();
86
            ViewDocument viewdoc = (ViewDocument) application.getActiveDocument(ViewManager.TYPENAME);
87
            value = viewdoc;
88
        }
89

    
90
    }
91

    
92
    private class CurrentViewEnvelopeValue extends CachedValue<Geometry> {
93

    
94
        @Override
95
        protected void reload() {
96
            ApplicationManager application = ApplicationLocator.getManager();
97
            ViewDocument viewdoc = (ViewDocument) application.getActiveDocument(ViewManager.TYPENAME);
98
            if( viewdoc == null ) {
99
                value = null;
100
                return;
101
            }
102
            value = viewdoc.getMapContext().getViewPort().getEnvelope().getGeometry();
103
        }
104

    
105
    }
106

    
107
    private class PropertiesValue extends CachedValue<Map<File, Properties>> {
108

    
109
        @Override
110
        protected void reload() {
111
            value = new HashMap<>();
112
        }
113
    }
114

    
115
    private class CurrentProjectFunction extends AbstractFunction {
116

    
117
        public CurrentProjectFunction() {
118
            super(
119
                    "Project",
120
                    "project",
121
                    Range.is(0),
122
                    "Access to the current project loaded in gvSIG desktop.\n",
123
                    "project()",
124
                    null,
125
                    "Project"
126
            );
127
        }
128

    
129
        @Override
130
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
131
            return currentProject.get();
132
        }
133

    
134
    }
135

    
136
    private class FirstSelectedFeatureFunction extends AbstractFunction {
137

    
138
        public FirstSelectedFeatureFunction() {
139
            super(
140
                    "Project",
141
                    "firstSelectedFeature",
142
                    Range.between(3, 4),
143
                    "Access to the first selected feature of the layer, and "
144
                    + "return the value of the attribute.",
145
                    "firstSelectedFeature({{view}}, layer, attribute, defaulValue)",
146
                    new String[]{
147
                        "view - String value with the name of a view",
148
                        "layer - String value with the name of a layer in the indicated view",
149
                        "attribute - String value with the name of the attribute in the indicated layer",
150
                        "defaultValue - Optional. Value to use if the indicated "
151
                        + "attribute can not be accessed. For example, if the "
152
                        + "view or layer does not exist, or it does not have "
153
                        + "selected elements."
154
                    },
155
                    "Object"
156
            );
157
        }
158

    
159
        @Override
160
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
161
            Object defaultValue = null;
162
            String viewName = getStr(args, 0);
163
            String layerName = getStr(args, 1);
164
            String attrName = getStr(args, 2);
165
            if (args.length == 4) {
166
                defaultValue = getObject(args, 3);
167
            }
168
            try {
169
                Project project = currentProject.get();
170
                ViewDocument view = (ViewDocument) project.getDocument(viewName, ViewManager.TYPENAME);
171
                if (view == null) {
172
                    return defaultValue;
173
                }
174
                FLayer layer = view.getLayer(layerName);
175
                if (!(layer instanceof FLyrVect)) {
176
                    return defaultValue;
177
                }
178
                FeatureSelection selection = ((FLyrVect) layer).getFeatureStore().getFeatureSelection();
179
                if (selection == null || selection.isEmpty()) {
180
                    return defaultValue;
181
                }
182
                Feature feature = selection.first();
183
                if (feature == null) {
184
                    return defaultValue;
185
                }
186
                return feature.get(attrName);
187
            } catch (Exception ex) {
188
                return defaultValue;
189
            }
190
        }
191

    
192
    }
193

    
194
    private class FirstLayerFeatureFunction extends AbstractFunction {
195

    
196
        public FirstLayerFeatureFunction() {
197
            super(
198
                    "Project",
199
                    FIRSTLAYERFEATURE_NAME,
200
                    Range.between(3, 6),
201
                    "Access to the first feature of the layer, and "
202
                    + "return the value of the attribute.",
203
                    FIRSTLAYERFEATURE_NAME+"({{view}}, layer, attribute, filter, order, defaulValue)",
204
                    new String[]{
205
                        "view - String value with the name of a view",
206
                        "layer - String value with the name of a layer in the indicated view",
207
                        "attribute - String value with the name of the attribute in the indicated layer",
208
                        "filter - Optional. String value with a filter expression",
209
                        "order - Optional. String value with the order. must be a string with the names of separate fields with commas",
210
                        "defaultValue - Optional. Value to use if the indicated "
211
                        + "attribute can not be accessed. For example, if the "
212
                        + "view or layer does not exist."
213
                    },
214
                    "Object"
215
            );
216
        }
217

    
218
        @Override
219
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
220
            Object defaultValue = null;
221
            String filter = null;
222
            String order = null;
223
            String viewName = getStr(args, 0);
224
            String layerName = getStr(args, 1);
225
            String attrName = getStr(args, 2);
226
            switch (args.length) {
227
                case 4:
228
                    filter = getStr(args, 3);
229
                    break;
230
                case 5:
231
                    filter = getStr(args, 3);
232
                    order = getStr(args, 4);
233
                    break;
234
                case 6:
235
                    filter = getStr(args, 3);
236
                    order = getStr(args, 4);
237
                    defaultValue = getObject(args, 6);
238
                    break;
239
            }
240
            try {
241
                Project project = currentProject.get();
242
                ViewDocument view = (ViewDocument) project.getDocument(viewName, ViewManager.TYPENAME);
243
                if (view == null) {
244
                    return defaultValue;
245
                }
246
                FLayer layer = view.getLayer(layerName);
247
                if (!(layer instanceof FLyrVect)) {
248
                    return defaultValue;
249
                }
250
                FeatureStore store = ((FLyrVect) layer).getFeatureStore();
251
                FeatureSet set;
252
                if (filter == null && order == null) {
253
                    set = store.getFeatureSet();
254
                } else {
255
                    FeatureQuery query = store.createFeatureQuery();
256
                    if (filter != null) {
257
                        query.addFilter(filter);
258
                    }
259
                    if (order != null) {
260
                        query.getOrder().add(order);
261
                    }
262
                    query.retrievesAllAttributes();
263
                    set = store.getFeatureSet(query);
264
                }
265
                Feature feature = set.first();
266
                if (feature == null) {
267
                    return defaultValue;
268
                }
269
                return feature.get(attrName);
270
            } catch (Exception ex) {
271
                return defaultValue;
272
            }
273
        }
274

    
275
    }
276

    
277
    private class ViewFunction extends AbstractFunction {
278

    
279
        public ViewFunction() {
280
            super(
281
                    "Project",
282
                    "view",
283
                    Range.is(1),
284
                    "Access to the indicated view",
285
                    "view({{viewName}})",
286
                    new String[]{
287
                        "view - String value with the name of a view"
288
                    },
289
                    "DocumentView"
290
            );
291
        }
292

    
293
        @Override
294
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
295
            String viewName = getStr(args, 0);
296
            Project project = currentProject.get();
297
            ViewDocument view = (ViewDocument) project.getDocument(viewName, ViewManager.TYPENAME);
298
            return view;
299
        }
300

    
301
    }
302

    
303
    private class ViewBBoxFunction extends AbstractFunction {
304

    
305
        public ViewBBoxFunction() {
306
            super(
307
                    "Project",
308
                    "viewbbox",
309
                    Range.is(0),
310
                    "Return the BBox of the active view.",
311
                    "viewbbox()",
312
                    null,
313
                    "Geometry"
314
            );
315
        }
316

    
317
        @Override
318
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
319
            return currentViewEnvelope.get();
320
        }
321

    
322
    }
323

    
324

    
325
    private class SavedPointFunction extends AbstractFunction {
326

    
327
        public SavedPointFunction() {
328
            super(
329
                    "Project",
330
                    "savedpoint",
331
                    Range.is(1),
332
                    "Return the value of the saved point with the name indicated.\n"
333
                            + "If the named point do not exists return null.",
334
                    "savedpoint({{name}})",
335
                    new String[]{
336
                        "name - String value with the name of the point"
337
                    },
338
                    "Geometry"
339
            );
340
        }
341

    
342
        @Override
343
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
344
            TemporaryStorageManager manager = TemporaryStorageLocator.getTemporaryStorageManager();
345
            TemporaryStorageGroup storage = manager.create("Points",Point.class);
346
            Geometry value = (Geometry) storage.get(getStr(args, 0));
347
            return value;
348
        }
349

    
350
    }
351

    
352
    private  class AreaFunction extends AbstractFunction {
353
        
354
        public AreaFunction() {
355
            super(
356
                    "Project",
357
                    AREA_NAME,
358
                    Range.between(2,3),
359
                    "Calculate the area of the geometry in the indicated units",
360
                    AREA_NAME+"({{geometry}}, 'm?')",
361
                    new String[]{
362
                        "geometry - Geometry",
363
                        "Projection - Optional. Projection of the geometry or a string with the projection name",
364
                        "units - String value with the name the units to use"
365
                    },
366
                    "Double"
367
            );
368
        }
369

    
370
        @Override
371
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
372
            int units = 0;
373
            IProjection proj = null;
374
            Geometry geom = getGeom(args, 0);
375
            switch( args.length ) {
376
                case 2:
377
                    units = getUnits(args, 1);
378
                    break;
379
                case 3:
380
                    proj = getProjection(args, 1);
381
                    units = getUnits(args, 2);
382
                    break;
383
            }
384
            if (proj == null) {
385
                proj = geom.getProjection();
386
            }
387
            AreaAndPerimeterCalculator calculator = new AreaAndPerimeterCalculator();
388
            double area = calculator.area(geom, proj, units);
389
            return area;
390
        }
391
    }
392

    
393
    private class PerimeterFunction extends AbstractFunction {
394

    
395
        public PerimeterFunction() {
396
            super(
397
                    "Project",
398
                    PERIMETER_NAME,
399
                    Range.between(2,3),
400
                    "Calculate the perimeter of the geometry in the indicated units",
401
                    PERIMETER_NAME+"({{geometry}}, 'm')",
402
                    new String[]{
403
                        "geometry - Geometry",
404
                        "Projection - Optional. Projection of the geometry or a string with the projection name",
405
                        "units - String value with the name the units to use"
406
                    },
407
                    "Double"
408
            );
409
        }
410

    
411
        @Override
412
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
413
            int units = 0;
414
            IProjection proj = null;
415
            Geometry geom = getGeom(args, 0);
416
            switch( args.length ) {
417
                case 2:
418
                    units = getUnits(args, 1);
419
                    break;
420
                case 3:
421
                    proj = getProjection(args, 1);
422
                    units = getUnits(args, 2);
423
                    break;
424
            }
425
            if (proj == null) {
426
                proj = geom.getProjection();
427
            }
428
            AreaAndPerimeterCalculator calculator = new AreaAndPerimeterCalculator();
429
            double area = calculator.perimeter(geom, proj, units);
430
            return area;
431
        }
432
    }
433

    
434
    private class PropertyFunction extends AbstractFunction {
435

    
436
        public PropertyFunction() {
437
            super(
438
                    "Project",
439
                    "property",
440
                    Range.between(2, 3),
441
                    "Access to a property value in a properties file. If the"
442
                    + "indicated filename is not absolute, access it relative"
443
                    + "to the project.",
444
                    "property({{filename}}, name, defaultValue)",
445
                    new String[]{
446
                        "filename - String value with the name of the properties file",
447
                        "name - String value with the name of the property to retrieve from the file",
448
                        "defaultValue - Optional. Default value if can't access the file or the property",},
449
                    "String"
450
            );
451
        }
452

    
453
        @Override
454
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
455
            String filename = getStr(args, 0);
456
            String name = getStr(args, 1);
457
            String defaultValue = null;
458
            if (args.length == 3) {
459
                defaultValue = getStr(args, 2);
460
            }
461

    
462
            File file = new File(filename);
463
            if (!file.isAbsolute()) {
464
                Project project = currentProject.get();
465
                if (project.getFile() == null) {
466
                    return defaultValue;
467
                }
468
                file = new File(project.getFile().getParent(), filename);
469
            }
470
            Map<File, Properties> x = propertiesFiles.get();
471
            Properties properties = x.get(file);
472
            if (properties == null) {
473
                properties = new Properties();
474
                FileInputStream in = null;
475
                try {
476
                    in = new FileInputStream(file);
477
                    properties.load(in);
478
                } catch (Exception ex) {
479
                    return defaultValue;
480
                } finally {
481
                    IOUtils.closeQuietly(in);
482
                }
483
                x.put(file, properties);
484
            }
485
            String value = properties.getProperty(name, defaultValue);
486
            return value;
487
        }
488

    
489
    }
490

    
491
    ProjectValue currentProject = new ProjectValue();
492
    CurrentViewValue currentView = new CurrentViewValue();
493
    CurrentViewEnvelopeValue currentViewEnvelope = new CurrentViewEnvelopeValue();
494
    PropertiesValue propertiesFiles = new PropertiesValue();
495

    
496
    @SuppressWarnings("OverridableMethodCallInConstructor")
497
    public ProjectSymbolTable() {
498
        super(NAME);
499
        this.addFunction(new CurrentProjectFunction());
500
        this.addFunction(new FirstSelectedFeatureFunction());
501
        this.addFunction(new FirstLayerFeatureFunction());
502
        this.addFunction(new ViewFunction());
503
        this.addFunction(new ViewBBoxFunction());
504
        this.addFunction(new PropertyFunction());
505
        this.addFunction(new AreaFunction());
506
        this.addFunction(new PerimeterFunction());
507
        this.addFunction(new SavedPointFunction());
508
    }
509

    
510
    private MapContext getMapContext(Feature feature) {
511
        FeatureStore store = feature.getStore();
512
        Project project = ProjectManager.getInstance().getCurrentProject();
513
        project.getDocuments(ViewManager.TYPENAME);
514
        for (Document document : project.getDocuments(ViewManager.TYPENAME)) {
515
            ViewDocument view = (ViewDocument) document;
516
            MapContext mapContext = view.getMapContext();
517
            FLayer layer = getLayer(mapContext, store);
518
            if (layer != null) {
519
                return mapContext;
520
            }
521
        }
522
        return null;
523
    }
524

    
525
    private FLayer getLayer(MapContext mapContext, FeatureStore store) {
526
        Iterator<FLayer> it = mapContext.deepiterator();
527
        while (it.hasNext()) {
528
            FLayer layer = it.next();
529
            if (layer instanceof FLyrVect) {
530
                FeatureStore layer_store = ((FLyrVect) layer).getFeatureStore();
531
                if (layer_store == store) {
532
                    return layer;
533
                }
534
            }
535
        }
536
        return null;
537
    }
538

    
539
    private IProjection getProjection(Object[] args, int i) {
540
        Object value = args[i];
541
        if (value == null) {
542
            return null;
543
        }
544
        if (value instanceof IProjection) {
545
            return (IProjection) value;
546
        }
547
        String code = value.toString();
548
        return CRSFactory.getCRS(code);
549
    }
550

    
551
    private int getUnits(Object[] args, int i) {
552
        Object value = args[i];
553
        if (value == null) {
554
            throw new IllegalArgumentException("Illegal unit value 'null'");
555
        }
556
        if (value instanceof Number) {
557
            return ((Number) value).intValue();
558
        }
559
        String name = value.toString();
560
        String[] names = MapContext.getAreaAbbr();
561
        for (int j = 0; j < names.length; j++) {
562
            if (name.equalsIgnoreCase(names[j])) {
563
                return j;
564
            }
565
        }
566
        names = MapContext.getAreaNames();
567
        for (int j = 0; j < names.length; j++) {
568
            if (name.equalsIgnoreCase(names[j])) {
569
                return j;
570
            }
571
        }
572
        throw new IllegalArgumentException("Illegal unit name '" + name + "'");
573
    }
574

    
575
}