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 @ 44189

History | View | Annotate | Download (22.5 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.Expression;
20
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
21
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
22
import org.gvsig.expressionevaluator.ExpressionRuntimeException;
23
import org.gvsig.expressionevaluator.Interpreter;
24
import org.gvsig.expressionevaluator.spi.AbstractFunction;
25
import org.gvsig.expressionevaluator.spi.AbstractSymbolTable;
26
import org.gvsig.fmap.crs.CRSFactory;
27
import org.gvsig.fmap.dal.DALLocator;
28
import org.gvsig.fmap.dal.DataManager;
29
import org.gvsig.fmap.dal.HasDataStore;
30
import org.gvsig.fmap.dal.expressionevaluator.FeatureSymbolTable;
31
import org.gvsig.fmap.dal.feature.Feature;
32
import org.gvsig.fmap.dal.feature.FeatureQuery;
33
import org.gvsig.fmap.dal.feature.FeatureSet;
34
import org.gvsig.fmap.dal.feature.FeatureStore;
35
import org.gvsig.fmap.geom.Geometry;
36
import org.gvsig.fmap.geom.primitive.Point;
37
import org.gvsig.fmap.mapcontext.MapContext;
38
import org.gvsig.fmap.mapcontext.layers.FLayer;
39
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
40
import org.gvsig.fmap.mapcontrol.AreaAndPerimeterCalculator;
41
import org.gvsig.temporarystorage.TemporaryStorageGroup;
42
import org.gvsig.temporarystorage.TemporaryStorageLocator;
43
import org.gvsig.temporarystorage.TemporaryStorageManager;
44

    
45
/**
46
 *
47
 * @author jjdelcerro
48
 */
49
@SuppressWarnings("UseSpecificCatch")
50
public class ProjectSymbolTable extends AbstractSymbolTable {
51

    
52
    public static final String AREA_NAME = "AREA";        
53
    public static final String PERIMETER_NAME = "PERIMETER";
54
    public static final String STORE_NAME = "STORE";
55
    public static final String FETCH_FIRST_NAME = "FETCH_FIRST";
56
    public static final String FETCH_FIRST_SELECTED_NAME = "FETCH_FIRST_SELECTED";
57
        
58
    static final String NAME = "Project";
59
    
60
    private static final String TABLE_DOCUMENT_TYPENAME = "project.document.table";
61
    
62
    private abstract class CachedValue<T> {
63

    
64
        T value = null;
65
        long lastAccess = 0;
66

    
67
        protected abstract void reload();
68

    
69
        public boolean isExpired() {
70
            long now = System.currentTimeMillis();
71
            return now - lastAccess > 3000;
72
        }
73

    
74
        public T get() {
75
            if (isExpired()) {
76
                reload();
77
            }
78
            lastAccess = System.currentTimeMillis();
79
            return value;
80
        }
81
    }
82

    
83
    private class ProjectValue extends CachedValue<Project> {
84

    
85
        @Override
86
        protected void reload() {
87
            value = ProjectManager.getInstance().getCurrentProject();
88
        }
89

    
90
    }
91

    
92
    private class CurrentViewValue extends CachedValue<ViewDocument> {
93

    
94
        @Override
95
        protected void reload() {
96
            ApplicationManager application = ApplicationLocator.getManager();
97
            ViewDocument viewdoc = (ViewDocument) application.getActiveDocument(ViewManager.TYPENAME);
98
            value = viewdoc;
99
        }
100

    
101
    }
102

    
103
    private class CurrentViewEnvelopeValue extends CachedValue<Geometry> {
104

    
105
        @Override
106
        protected void reload() {
107
            ApplicationManager application = ApplicationLocator.getManager();
108
            ViewDocument viewdoc = (ViewDocument) application.getActiveDocument(ViewManager.TYPENAME);
109
            if( viewdoc == null ) {
110
                value = null;
111
                return;
112
            }
113
            value = viewdoc.getMapContext().getViewPort().getEnvelope().getGeometry();
114
        }
115

    
116
    }
117

    
118
    private class PropertiesValue extends CachedValue<Map<File, Properties>> {
119

    
120
        @Override
121
        protected void reload() {
122
            value = new HashMap<>();
123
        }
124
    }
125

    
126
    private class CurrentProjectFunction extends AbstractFunction {
127

    
128
        public CurrentProjectFunction() {
129
            super(
130
                    "Project",
131
                    "project",
132
                    Range.is(0),
133
                    "Access to the current project loaded in gvSIG desktop.\n",
134
                    "project()",
135
                    null,
136
                    "Project"
137
            );
138
        }
139

    
140
        @Override
141
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
142
            return currentProject.get();
143
        }
144

    
145
    }
146

    
147
    private class StoreFunction extends AbstractFunction {
148

    
149
        public StoreFunction() {
150
            super(
151
                    "Project",
152
                    STORE_NAME,
153
                    Range.is(2), // Range.between(1, 2),
154
                    "Return the data store associated with a layer.", // or a table.\n" +
155
//                       "If receive a single parameter, it will correspond to " + 
156
//                       "the name of a table-type document, and it will return " + 
157
//                       "your data store. If you receive two parameters, you expect " +
158
//                       "to be the name of a view and a layer of it, returning the " +
159
//                       "data store of the layer.",
160
                    STORE_NAME+"({{view}}, layer)",
161
                    new String[]{
162
                        "view - String value with the name of a view",
163
                        "layer - String value with the name of a layer in the indicated view"
164
//                        "table - String value with the name of document table"
165
                    },
166
                    "DataStore"
167
            );
168
        }
169

    
170
        @Override
171
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
172
            Project project = currentProject.get();
173
            switch (args.length) {
174
                case 1:
175
                    String tableName = getStr(args, 0);
176
                    Document document = project.getDocument(tableName, TABLE_DOCUMENT_TYPENAME);
177
                    if (document == null) {
178
                        return null;
179
                    }
180
                    if( document instanceof HasDataStore ) {
181
                        return ((HasDataStore) document).getDataStore();
182
                    }
183
                    return null;
184

    
185
                case 2:
186
                    String viewName = getStr(args, 0);
187
                    String layerName = getStr(args, 1);
188
                    ViewDocument view = (ViewDocument) project.getDocument(viewName, ViewManager.TYPENAME);
189
                    if (view == null) {
190
                        return null;
191
                    }
192
                    FLayer layer = view.getLayer(layerName);
193
                    if( layer instanceof HasDataStore ) {
194
                        return ((HasDataStore)layer).getDataStore();
195
                    }
196
                    return null;
197
            }
198
            return null;
199
        }
200
        
201
    }
202
    
203
    private class FetchFirstFunction extends AbstractFunction {
204

    
205
        public FetchFirstFunction() {
206
            super(
207
                    "Project",
208
                    FETCH_FIRST_NAME,
209
                    Range.between(2, 4),
210
                    "Access to the first feature of the layer, and "
211
                    + "return the value of the attribute.",
212
                    FETCH_FIRST_NAME+"({{value}}, store, where, order)",
213
                    new String[]{
214
                        "value - value to retrieve from the store, usually an expression in the columns of this are involved.",
215
                        "store - data store from which values will be collected",
216
                        "where - Optional. String value with a filter expression",
217
                        "order - Optional. String value with the order. must be a string with the names of separate fields with commas"
218
                    },
219
                    "Object"
220
            );
221
        }
222

    
223
        @Override
224
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
225
            Object value;
226
            String where = null;
227
            String order = null;
228
            String expression_s = getStr(args, 0);
229
            FeatureStore store = (FeatureStore) getObject(args, 1);
230
            switch (args.length) {
231
                case 3:
232
                    where = getStr(args, 2);
233
                    break;
234
                case 4:
235
                    where = getStr(args, 2);
236
                    order = getStr(args, 3);
237
                    break;
238
            }
239
            try {
240
                FeatureSet set;
241
                if (where == null && order == null) {
242
                    set = store.getFeatureSet();
243
                } else {
244
                    FeatureQuery query = store.createFeatureQuery();
245
                    if (where != null) {
246
                        query.addFilter(where);
247
                    }
248
                    if (order != null) {
249
                        query.getOrder().add(order);
250
                    }
251
                    query.retrievesAllAttributes();
252
                    set = store.getFeatureSet(query);
253
                }
254
                Feature feature = set.first();
255
                if (feature == null) {
256
                    return null;
257
                }
258
                DataManager dataManager = DALLocator.getDataManager();
259
                FeatureSymbolTable symbolTable = dataManager.createFeatureSymbolTable();
260
                symbolTable.setFeature(feature);
261

    
262
                ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
263
                Expression expression = expManager.createExpression();
264
                expression.setPhrase(expression_s);
265
                value = expression.execute(symbolTable.createParent());
266
                
267
                return value;
268
            } catch (Exception ex) {
269
                throw new ExpressionRuntimeException("Problems calling '"+FETCH_FIRST_NAME+"' function", ex);
270
            }
271
        }
272
    }
273

    
274
    private class FetchFirstSelectedFunction extends AbstractFunction {
275

    
276
        public FetchFirstSelectedFunction() {
277
            super("Project",
278
                    FETCH_FIRST_SELECTED_NAME,
279
                    Range.is(2),
280
                    "Access to the first feature of the selection.",
281
                    FETCH_FIRST_SELECTED_NAME+"({{value}}, store)",
282
                    new String[]{
283
                        "value - value to retrieve from the store, usually an expression in the columns of this are involved.",
284
                        "store - data store from which values will be collected"
285
                    },
286
                    "Object"
287
            );
288
        }
289

    
290
        @Override
291
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
292
            String expression_s = getStr(args, 0);
293
            FeatureStore store = (FeatureStore) getObject(args, 1);
294
            try {
295
                FeatureSet set = store.getFeatureSelection();
296
                Feature feature = set.first();
297
                if (feature == null) {
298
                    return null;
299
                }
300
                DataManager dataManager = DALLocator.getDataManager();
301
                FeatureSymbolTable symbolTable = dataManager.createFeatureSymbolTable();
302
                symbolTable.setFeature(feature);
303

    
304
                ExpressionEvaluatorManager expManager = ExpressionEvaluatorLocator.getManager();
305
                Expression expression = expManager.createExpression();
306
                expression.setPhrase(expression_s);
307
                Object value = expression.execute(symbolTable.createParent());
308
                
309
                return value;
310
            } catch (Exception ex) {
311
                throw new ExpressionRuntimeException("Problems calling '"+FETCH_FIRST_SELECTED_NAME+"' function", ex);
312
            }
313
        }
314
    }
315

    
316
    private class ViewFunction extends AbstractFunction {
317

    
318
        public ViewFunction() {
319
            super(
320
                    "Project",
321
                    "view",
322
                    Range.is(1),
323
                    "Access to the indicated view",
324
                    "view({{viewName}})",
325
                    new String[]{
326
                        "view - String value with the name of a view"
327
                    },
328
                    "DocumentView"
329
            );
330
        }
331

    
332
        @Override
333
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
334
            String viewName = getStr(args, 0);
335
            Project project = currentProject.get();
336
            ViewDocument view = (ViewDocument) project.getDocument(viewName, ViewManager.TYPENAME);
337
            return view;
338
        }
339

    
340
    }
341

    
342
    private class ViewBBoxFunction extends AbstractFunction {
343

    
344
        public ViewBBoxFunction() {
345
            super(
346
                    "Project",
347
                    "viewbbox",
348
                    Range.is(0),
349
                    "Return the BBox of the active view.",
350
                    "viewbbox()",
351
                    null,
352
                    "Geometry"
353
            );
354
        }
355

    
356
        @Override
357
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
358
            return currentViewEnvelope.get();
359
        }
360

    
361
    }
362

    
363

    
364
    private class SavedPointFunction extends AbstractFunction {
365

    
366
        public SavedPointFunction() {
367
            super(
368
                    "Project",
369
                    "savedpoint",
370
                    Range.is(1),
371
                    "Return the value of the saved point with the name indicated.\n"
372
                            + "If the named point do not exists return null.",
373
                    "savedpoint({{name}})",
374
                    new String[]{
375
                        "name - String value with the name of the point"
376
                    },
377
                    "Geometry"
378
            );
379
        }
380

    
381
        @Override
382
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
383
            TemporaryStorageManager manager = TemporaryStorageLocator.getTemporaryStorageManager();
384
            TemporaryStorageGroup storage = manager.create("Points",Point.class);
385
            Geometry value = (Geometry) storage.get(getStr(args, 0));
386
            return value;
387
        }
388

    
389
    }
390

    
391
    private  class AreaFunction extends AbstractFunction {
392
        
393
        public AreaFunction() {
394
            super(
395
                    "Project",
396
                    AREA_NAME,
397
                    Range.between(2,3),
398
                    "Calculate the area of the geometry in the indicated units",
399
                    AREA_NAME+"({{geometry}}, 'm?')",
400
                    new String[]{
401
                        "geometry - Geometry",
402
                        "Projection - Optional. Projection of the geometry or a string with the projection name",
403
                        "units - String value with the name the units to use"
404
                    },
405
                    "Double"
406
            );
407
        }
408

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

    
432
    private class PerimeterFunction extends AbstractFunction {
433

    
434
        public PerimeterFunction() {
435
            super(
436
                    "Project",
437
                    PERIMETER_NAME,
438
                    Range.between(2,3),
439
                    "Calculate the perimeter of the geometry in the indicated units",
440
                    PERIMETER_NAME+"({{geometry}}, 'm')",
441
                    new String[]{
442
                        "geometry - Geometry",
443
                        "Projection - Optional. Projection of the geometry or a string with the projection name",
444
                        "units - String value with the name the units to use"
445
                    },
446
                    "Double"
447
            );
448
        }
449

    
450
        @Override
451
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
452
            int units = 0;
453
            IProjection proj = null;
454
            Geometry geom = getGeom(args, 0);
455
            switch( args.length ) {
456
                case 2:
457
                    units = getUnits(args, 1);
458
                    break;
459
                case 3:
460
                    proj = getProjection(args, 1);
461
                    units = getUnits(args, 2);
462
                    break;
463
            }
464
            if (proj == null) {
465
                proj = geom.getProjection();
466
            }
467
            AreaAndPerimeterCalculator calculator = new AreaAndPerimeterCalculator();
468
            double area = calculator.perimeter(geom, proj, units);
469
            return area;
470
        }
471
    }
472

    
473
    private class PropertyFunction extends AbstractFunction {
474

    
475
        public PropertyFunction() {
476
            super(
477
                    "Project",
478
                    "property",
479
                    Range.between(2, 3),
480
                    "Access to a property value in a properties file. If the"
481
                    + "indicated filename is not absolute, access it relative"
482
                    + "to the project.",
483
                    "property({{filename}}, name, defaultValue)",
484
                    new String[]{
485
                        "filename - String value with the name of the properties file",
486
                        "name - String value with the name of the property to retrieve from the file",
487
                        "defaultValue - Optional. Default value if can't access the file or the property",},
488
                    "String"
489
            );
490
        }
491

    
492
        @Override
493
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
494
            String filename = getStr(args, 0);
495
            String name = getStr(args, 1);
496
            String defaultValue = null;
497
            if (args.length == 3) {
498
                defaultValue = getStr(args, 2);
499
            }
500

    
501
            File file = new File(filename);
502
            if (!file.isAbsolute()) {
503
                Project project = currentProject.get();
504
                if (project.getFile() == null) {
505
                    return defaultValue;
506
                }
507
                file = new File(project.getFile().getParent(), filename);
508
            }
509
            Map<File, Properties> x = propertiesFiles.get();
510
            Properties properties = x.get(file);
511
            if (properties == null) {
512
                properties = new Properties();
513
                FileInputStream in = null;
514
                try {
515
                    in = new FileInputStream(file);
516
                    properties.load(in);
517
                } catch (Exception ex) {
518
                    return defaultValue;
519
                } finally {
520
                    IOUtils.closeQuietly(in);
521
                }
522
                x.put(file, properties);
523
            }
524
            String value = properties.getProperty(name, defaultValue);
525
            return value;
526
        }
527

    
528
    }
529

    
530
    ProjectValue currentProject = new ProjectValue();
531
    CurrentViewValue currentView = new CurrentViewValue();
532
    CurrentViewEnvelopeValue currentViewEnvelope = new CurrentViewEnvelopeValue();
533
    PropertiesValue propertiesFiles = new PropertiesValue();
534

    
535
    @SuppressWarnings("OverridableMethodCallInConstructor")
536
    public ProjectSymbolTable() {
537
        super(NAME);
538
        this.addFunction(new CurrentProjectFunction());
539
        this.addFunction(new StoreFunction());
540
        this.addFunction(new FetchFirstFunction());
541
        this.addFunction(new FetchFirstSelectedFunction());
542
        this.addFunction(new ViewFunction());
543
        this.addFunction(new ViewBBoxFunction());
544
        this.addFunction(new PropertyFunction());
545
        this.addFunction(new AreaFunction());
546
        this.addFunction(new PerimeterFunction());
547
        this.addFunction(new SavedPointFunction());
548
    }
549

    
550
    private MapContext getMapContext(Feature feature) {
551
        FeatureStore store = feature.getStore();
552
        Project project = ProjectManager.getInstance().getCurrentProject();
553
        project.getDocuments(ViewManager.TYPENAME);
554
        for (Document document : project.getDocuments(ViewManager.TYPENAME)) {
555
            ViewDocument view = (ViewDocument) document;
556
            MapContext mapContext = view.getMapContext();
557
            FLayer layer = getLayer(mapContext, store);
558
            if (layer != null) {
559
                return mapContext;
560
            }
561
        }
562
        return null;
563
    }
564

    
565
    private FLayer getLayer(MapContext mapContext, FeatureStore store) {
566
        Iterator<FLayer> it = mapContext.deepiterator();
567
        while (it.hasNext()) {
568
            FLayer layer = it.next();
569
            if (layer instanceof FLyrVect) {
570
                FeatureStore layer_store = ((FLyrVect) layer).getFeatureStore();
571
                if (layer_store == store) {
572
                    return layer;
573
                }
574
            }
575
        }
576
        return null;
577
    }
578

    
579
    private IProjection getProjection(Object[] args, int i) {
580
        Object value = args[i];
581
        if (value == null) {
582
            return null;
583
        }
584
        if (value instanceof IProjection) {
585
            return (IProjection) value;
586
        }
587
        String code = value.toString();
588
        return CRSFactory.getCRS(code);
589
    }
590

    
591
    private int getUnits(Object[] args, int i) {
592
        Object value = args[i];
593
        if (value == null) {
594
            throw new IllegalArgumentException("Illegal unit value 'null'");
595
        }
596
        if (value instanceof Number) {
597
            return ((Number) value).intValue();
598
        }
599
        String name = value.toString();
600
        String[] names = MapContext.getAreaAbbr();
601
        for (int j = 0; j < names.length; j++) {
602
            if (name.equalsIgnoreCase(names[j])) {
603
                return j;
604
            }
605
        }
606
        names = MapContext.getAreaNames();
607
        for (int j = 0; j < names.length; j++) {
608
            if (name.equalsIgnoreCase(names[j])) {
609
                return j;
610
            }
611
        }
612
        throw new IllegalArgumentException("Illegal unit name '" + name + "'");
613
    }
614

    
615
}