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 / ProjectSymbolTable.java @ 44035

History | View | Annotate | Download (20.5 KB)

1
package org.gvsig.app.project;
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.documents.Document;
15
import org.gvsig.app.project.documents.view.ViewDocument;
16
import org.gvsig.app.project.documents.view.ViewManager;
17
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
18
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
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.Envelope;
30
import org.gvsig.fmap.geom.primitive.Point;
31
import org.gvsig.fmap.mapcontext.MapContext;
32
import org.gvsig.fmap.mapcontext.layers.FLayer;
33
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
34
import org.gvsig.fmap.mapcontrol.AreaAndPerimeterCalculator;
35
import org.gvsig.temporarystorage.TemporaryStorageGroup;
36
import org.gvsig.temporarystorage.TemporaryStorageLocator;
37
import org.gvsig.temporarystorage.TemporaryStorageManager;
38

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

    
46
    private abstract class CachedValue<T> {
47

    
48
        T value = null;
49
        long lastAccess = 0;
50

    
51
        protected abstract void reload();
52

    
53
        public boolean isExpired() {
54
            long now = System.currentTimeMillis();
55
            return now - lastAccess > 3000;
56
        }
57

    
58
        public T get() {
59
            if (isExpired()) {
60
                reload();
61
            }
62
            lastAccess = System.currentTimeMillis();
63
            return value;
64
        }
65
    }
66

    
67
    private class ProjectValue extends CachedValue<Project> {
68

    
69
        @Override
70
        protected void reload() {
71
            value = ProjectManager.getInstance().getCurrentProject();
72
        }
73

    
74
    }
75

    
76
    private class CurrentViewValue extends CachedValue<ViewDocument> {
77

    
78
        @Override
79
        protected void reload() {
80
            ApplicationManager application = ApplicationLocator.getManager();
81
            ViewDocument viewdoc = (ViewDocument) application.getActiveDocument(ViewManager.TYPENAME);
82
            value = viewdoc;
83
        }
84

    
85
    }
86

    
87
    private class CurrentViewEnvelopeValue extends CachedValue<Geometry> {
88

    
89
        @Override
90
        protected void reload() {
91
            ApplicationManager application = ApplicationLocator.getManager();
92
            ViewDocument viewdoc = (ViewDocument) application.getActiveDocument(ViewManager.TYPENAME);
93
            if( viewdoc == null ) {
94
                value = null;
95
                return;
96
            }
97
            value = viewdoc.getMapContext().getViewPort().getEnvelope().getGeometry();
98
        }
99

    
100
    }
101

    
102
    private class PropertiesValue extends CachedValue<Map<File, Properties>> {
103

    
104
        @Override
105
        protected void reload() {
106
            value = new HashMap<>();
107
        }
108
    }
109

    
110
    private class CurrentProjectFunction extends AbstractFunction {
111

    
112
        public CurrentProjectFunction() {
113
            super(
114
                    "Project",
115
                    "project",
116
                    Range.is(0),
117
                    "Access to the current project loaded in gvSIG desktop.\n",
118
                    "project()",
119
                    null,
120
                    "Project"
121
            );
122
        }
123

    
124
        @Override
125
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
126
            return currentProject.get();
127
        }
128

    
129
    }
130

    
131
    private class FirstSelectedFeatureFunction extends AbstractFunction {
132

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

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

    
187
    }
188

    
189
    private class FirstFeatureFunction extends AbstractFunction {
190

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

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

    
269
    }
270

    
271
    private class ViewFunction extends AbstractFunction {
272

    
273
        public ViewFunction() {
274
            super(
275
                    "Project",
276
                    "view",
277
                    Range.is(1),
278
                    "Access to the indicated view",
279
                    "view({{viewName}})",
280
                    new String[]{
281
                        "view - String value with the name of a view"
282
                    },
283
                    "DocumentView"
284
            );
285
        }
286

    
287
        @Override
288
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
289
            String viewName = getStr(args, 0);
290
            Project project = currentProject.get();
291
            ViewDocument view = (ViewDocument) project.getDocument(viewName, ViewManager.TYPENAME);
292
            return view;
293
        }
294

    
295
    }
296

    
297
    private class ViewBBoxFunction extends AbstractFunction {
298

    
299
        public ViewBBoxFunction() {
300
            super(
301
                    "Project",
302
                    "viewbbox",
303
                    Range.is(0),
304
                    "Return the BBox of the active view.",
305
                    "viewbbox()",
306
                    null,
307
                    "Geometry"
308
            );
309
        }
310

    
311
        @Override
312
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
313
            return currentViewEnvelope.get();
314
        }
315

    
316
    }
317

    
318

    
319
    private class SavedPointFunction extends AbstractFunction {
320

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

    
336
        @Override
337
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
338
            TemporaryStorageManager manager = TemporaryStorageLocator.getTemporaryStorageManager();
339
            TemporaryStorageGroup storage = manager.create("Points",Point.class);
340
            Geometry value = (Geometry) storage.get(getStr(args, 0));
341
            return value;
342
        }
343

    
344
    }
345

    
346
    private class AreaFunction extends AbstractFunction {
347

    
348
        public AreaFunction() {
349
            super(
350
                    "Project",
351
                    "Area",
352
                    Range.between(2,3),
353
                    "Calculate the area of the geometry in the indicated units",
354
                    "Area({{geometry}}, \"m\")",
355
                    new String[]{
356
                        "geometry - Geometry",
357
                        "Projection - Optional. Projection of the geometry or a string with the projection name",
358
                        "units - String value with the name the units to use"
359
                    },
360
                    "Double"
361
            );
362
        }
363

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

    
387
    private class PerimeterFunction extends AbstractFunction {
388

    
389
        public PerimeterFunction() {
390
            super(
391
                    "Project",
392
                    "Perimeter",
393
                    Range.between(2,3),
394
                    "Calculate the perimeter of the geometry in the indicated units",
395
                    "Perimeter({{geometry}}, \"m\")",
396
                    new String[]{
397
                        "geometry - Geometry",
398
                        "Projection - Optional. Projection of the geometry or a string with the projection name",
399
                        "units - String value with the name the units to use"
400
                    },
401
                    "Double"
402
            );
403
        }
404

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

    
428
    private class PropertyFunction extends AbstractFunction {
429

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

    
447
        @Override
448
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
449
            String filename = getStr(args, 0);
450
            String name = getStr(args, 1);
451
            String defaultValue = null;
452
            if (args.length == 3) {
453
                defaultValue = getStr(args, 2);
454
            }
455

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

    
483
    }
484

    
485
    ProjectValue currentProject = new ProjectValue();
486
    CurrentViewValue currentView = new CurrentViewValue();
487
    CurrentViewEnvelopeValue currentViewEnvelope = new CurrentViewEnvelopeValue();
488
    PropertiesValue propertiesFiles = new PropertiesValue();
489

    
490
    @SuppressWarnings("OverridableMethodCallInConstructor")
491
    public ProjectSymbolTable() {
492
        super("Project");
493
        this.addFunction(new CurrentProjectFunction());
494
        this.addFunction(new FirstSelectedFeatureFunction());
495
        this.addFunction(new FirstFeatureFunction());
496
        this.addFunction(new ViewFunction());
497
        this.addFunction(new ViewBBoxFunction());
498
        this.addFunction(new PropertyFunction());
499
        this.addFunction(new AreaFunction());
500
        this.addFunction(new PerimeterFunction());
501
        this.addFunction(new SavedPointFunction());
502
    }
503

    
504
    private MapContext getMapContext(Feature feature) {
505
        FeatureStore store = feature.getStore();
506
        Project project = ProjectManager.getInstance().getCurrentProject();
507
        project.getDocuments(ViewManager.TYPENAME);
508
        for (Document document : project.getDocuments(ViewManager.TYPENAME)) {
509
            ViewDocument view = (ViewDocument) document;
510
            MapContext mapContext = view.getMapContext();
511
            FLayer layer = getLayer(mapContext, store);
512
            if (layer != null) {
513
                return mapContext;
514
            }
515
        }
516
        return null;
517
    }
518

    
519
    private FLayer getLayer(MapContext mapContext, FeatureStore store) {
520
        Iterator<FLayer> it = mapContext.deepiterator();
521
        while (it.hasNext()) {
522
            FLayer layer = it.next();
523
            if (layer instanceof FLyrVect) {
524
                FeatureStore layer_store = ((FLyrVect) layer).getFeatureStore();
525
                if (layer_store == store) {
526
                    return layer;
527
                }
528
            }
529
        }
530
        return null;
531
    }
532

    
533
    private IProjection getProjection(Object[] args, int i) {
534
        Object value = args[i];
535
        if (value == null) {
536
            return null;
537
        }
538
        if (value instanceof IProjection) {
539
            return (IProjection) value;
540
        }
541
        String code = value.toString();
542
        return CRSFactory.getCRS(code);
543
    }
544

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

    
569
    public static void selfRegister() {
570
        ExpressionEvaluatorManager manager = ExpressionEvaluatorLocator.getManager();
571
        manager.registerSymbolTable(new ProjectSymbolTable(), true);
572
    }
573
}