Statistics
| Revision:

gvsig-projects-pool / org.gvsig.online / trunk / org.gvsig.online / org.gvsig.online.lib / org.gvsig.online.lib.impl / src / main / java / org / gvsig / online / lib / impl / OnlineLayerImpl.java @ 9522

History | View | Annotate | Download (18.5 KB)

1
package org.gvsig.online.lib.impl;
2

    
3
import java.awt.Dimension;
4
import java.io.File;
5
import java.io.FileInputStream;
6
import java.net.URL;
7
import java.nio.charset.StandardCharsets;
8
import java.util.Iterator;
9
import java.util.List;
10
import java.util.Locale;
11
import java.util.NoSuchElementException;
12
import javax.json.JsonArray;
13
import javax.json.JsonObject;
14
import javax.json.JsonValue;
15
import org.apache.commons.io.FileUtils;
16
import org.apache.commons.io.IOUtils;
17
import org.apache.commons.lang3.BooleanUtils;
18
import org.apache.commons.lang3.StringUtils;
19
import org.cresques.cts.IProjection;
20
import org.gvsig.fmap.crs.CRSFactory;
21
import org.gvsig.fmap.dal.DALLocator;
22
import org.gvsig.fmap.dal.DataTypes;
23
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
24
import org.gvsig.fmap.dal.feature.EditableFeatureType;
25
import org.gvsig.fmap.dal.feature.Feature;
26
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
27
import org.gvsig.fmap.dal.feature.FeatureType;
28
import org.gvsig.fmap.geom.Geometry;
29
import org.gvsig.fmap.geom.GeometryUtils;
30
import org.gvsig.fmap.geom.primitive.Envelope;
31
import org.gvsig.fmap.geom.type.GeometryType;
32
import org.gvsig.json.Json;
33
import org.gvsig.json.SupportFromJson;
34
import org.gvsig.online.lib.api.OnlineDownloader;
35
import org.gvsig.online.lib.api.OnlineLayer;
36
import static org.gvsig.online.lib.api.OnlineManager.FEATUREDATE_FIELD_NAME;
37
import static org.gvsig.online.lib.api.OnlineManager.FEATURELASTMODIFICATION_FIELD_NAME;
38
import static org.gvsig.online.lib.api.OnlineManager.FEATUREMODIFIEDBY_FIELD_NAME;
39
import static org.gvsig.online.lib.api.OnlineManager.FEATUREVERSION_FIELD_NAME;
40
import org.gvsig.online.lib.api.OnlineProject;
41
import org.gvsig.online.lib.api.OnlineSite;
42
import org.gvsig.tools.task.SimpleTaskStatus;
43
import org.slf4j.Logger;
44
import org.slf4j.LoggerFactory;
45

    
46
/**
47
 *
48
 * @author jjdelcerro
49
 */
50
@SuppressWarnings("UseSpecificCatch")
51
public final class OnlineLayerImpl
52
        implements
53
        OnlineLayer,
54
        SupportFromJson {
55

    
56
    private static final Logger LOGGER = LoggerFactory.getLogger(OnlineLayerImpl.class);
57
    
58
    private JsonObject data;
59
    private OnlineSiteImpl site;
60
    private FeatureType featureType;
61
    private OnlineProjectImpl project;
62
    private Envelope envelope;
63
    private IProjection projection;
64

    
65
    private static class LayerDataImpl implements LayerData {
66
        
67
        private final int totalsize;
68
        private final int pagesize;
69
        private final int page;
70
        private final List<JsonValue> elements;
71
        
72
        public LayerDataImpl(int totalsize, int pagesize, int page, List<JsonValue> elements) {
73
            this.elements = elements;
74
            this.totalsize = totalsize;
75
            this.pagesize = pagesize;
76
            this.page = page;
77
        }
78

    
79
        @Override
80
        public int getPageElements() {
81
            return this.pagesize;
82
        }
83
        
84
        @Override
85
        public int getPage() {
86
            return this.page;
87
        }
88
        
89
        @Override
90
        public int getTotalElemens() {
91
            return this.totalsize;
92
        }
93
        
94
        @Override
95
        public Iterator<JsonObject> iterator() {
96
            Iterator<JsonValue> it = this.elements.iterator();
97
            return new Iterator<JsonObject>() {
98
                @Override
99
                public boolean hasNext() {
100
                    return it.hasNext();
101
                }
102

    
103
                @Override
104
                public JsonObject next() {
105
                    return (JsonObject) it.next();
106
                }
107
            };
108
        }
109
        
110
    }
111
            
112
    private static class LayerDataIterator implements Iterator<JsonObject> {
113

    
114
        private final int pageSize;
115
        private final OnlineLayerImpl layer;
116
        private final Envelope area;
117

    
118
        private int page;
119
        private LayerData theData;
120
        private Iterator<JsonObject> it;
121
        private final SimpleTaskStatus status;
122

    
123
        public LayerDataIterator(OnlineLayerImpl layer, Envelope area, int pageSize, SimpleTaskStatus status) {
124
            this.layer = layer;
125
            this.area = area;
126
            this.pageSize = pageSize;
127
            this.page = 0;
128
            this.theData = null;
129
            this.it = null;
130
            this.status = status;
131
        }
132

    
133
        @Override
134
        public boolean hasNext() {
135
            while (true) {
136
                if (this.theData != null) {
137
                    if (this.it.hasNext()) {
138
                        return true;
139
                    }
140
                    if (this.theData.getPageElements() < this.pageSize) {
141
                        return false;
142
                    }
143
                }
144
                this.theData = this.layer.getDataPage(this.area, this.pageSize, this.page++);
145
                if( this.theData == null ) {
146
                    return false;
147
                }
148
                if( status!=null ) {
149
                    this.status.setRangeOfValues(0, this.theData.getTotalElemens());
150
                    this.status.setCurValue(0);
151
                }
152
                this.it = this.theData.iterator();
153
            }
154
        }
155

    
156
        @Override
157
        public JsonObject next() {
158
            if (this.theData == null || this.it == null ) {
159
                if( this.hasNext() ) {
160
                    if( status!=null ) {
161
                        this.status.incrementCurrentValue();
162
                    }
163
                    return (JsonObject) this.it.next();
164
                }
165
                throw new NoSuchElementException();
166
            }
167
            if( this.it.hasNext() ) {
168
                if( status!=null ) {
169
                    this.status.incrementCurrentValue();
170
                }
171
                return (JsonObject) this.it.next();
172
            }
173
            if( this.hasNext() ) {
174
                if( status!=null ) {
175
                    this.status.incrementCurrentValue();
176
                }
177
                return (JsonObject) this.it.next();
178
            }
179
            throw new NoSuchElementException();
180
        }
181
    }
182

    
183
    public OnlineLayerImpl() {
184

    
185
    }
186

    
187
    public OnlineLayerImpl(OnlineSite site) {
188
        this.setSite(site);
189
    }
190

    
191
    public OnlineLayerImpl(OnlineSite site, JsonObject data) {
192
        this.setSite(site);
193
        this.fromJson(data);
194
    }
195

    
196
    public OnlineLayerImpl(OnlineProject project, JsonObject data) {
197
        this.setProject(project);
198
        this.fromJson(data);
199
    }
200

    
201
    public final OnlineLayerImpl setSite(OnlineSite site) {
202
        this.site = (OnlineSiteImpl) site;
203
        return this;
204
    }
205

    
206
    public final OnlineLayerImpl setProject(OnlineProject project) {
207
        this.project = (OnlineProjectImpl) project;
208
        this.site = (OnlineSiteImpl) this.project.getSite();
209
        return this;
210
    }
211

    
212
    @Override
213
    public OnlineSite getSite() {
214
        return this.site;
215
    }
216

    
217
    @Override
218
    public boolean isHidden() {
219
        String name = this.getName();
220
        if (this.project == null) {
221
            return false;
222
        }
223
        return StringUtils.equalsIgnoreCase(name, this.project.getConfigTableName())
224
                || StringUtils.equalsIgnoreCase(name, this.project.getResourcesTablaName());
225
    }
226

    
227
    @Override
228
    public int getId() {
229
        return this.data.getInt("id", -1);
230
    }
231

    
232
    @Override
233
    public String getName() {
234
        return this.data.getString("name", null);
235
    }
236

    
237
    @Override
238
    public String getTitle() {
239
        return this.data.getString("title", null);
240
    }
241

    
242
    @Override
243
    public String getWorkspace() {
244
        return this.data.getString("workspace", null);
245
    }
246

    
247
    @Override
248
    public String getLabel() {
249
        if (StringUtils.isNotBlank(this.getTitle())) {
250
            return this.getTitle();
251
        }
252
        if (StringUtils.isNotBlank(this.getName())) {
253
            return this.getName();
254
        }
255
        return String.valueOf(this.getId());
256
    }
257

    
258
    @Override
259
    public String getAbstract() {
260
        return this.data.getString("abstract", null);
261
    }
262

    
263
    @Override
264
    public String getType() {
265
        return this.data.getString("type", null);
266
    }
267

    
268
    @Override
269
    public int getlayerGroupId() {
270
        return this.data.getInt("layer_group_id", -1);
271
    }
272

    
273
    @Override
274
    public void fromJson(JsonObject json) {
275
        this.data = json;
276
    }
277

    
278
    @Override
279
    public String getSRS() {
280
        return this.data.getString("native_srs", null);
281
    }
282

    
283
    @Override
284
    public int getSRSCode() {
285
        try {
286
            String srs = this.getSRS();
287
            if (StringUtils.isBlank(srs)) {
288
                return 0;
289
            }
290
            return Integer.parseInt(StringUtils.split(srs, ':')[1]);
291
        } catch (Exception e) {
292
            return 0;
293
        }
294
    }
295

    
296
    @Override
297
    public String getPkName() {
298
        FeatureType ft = this.getFeatureType();
299
        FeatureAttributeDescriptor[] pk = ft.getPrimaryKey();
300
        if (pk == null) {
301
            return null;
302
        }
303
        return pk[0].getName();
304
    }
305

    
306
    @Override
307
    public FeatureType getFeatureType() {
308
        if (this.featureType != null) {
309
            return this.featureType;
310
        }
311
        // Se declaran las variables aqui para poder consultarlas en el catch
312
        int tableId = -1;
313
        String tableName = "unknown";        
314
        EditableFeatureType ftype = null;
315
        JsonObject description_json = null;
316
        JsonObject item = null;
317
        GeometryType geomtype = null;
318
        int type = DataTypes.UNKNOWN;
319
        int size = 0;
320
        File f = null;
321
        int precision = 0;
322
        int scale = 0;
323
        try {
324
            tableId = this.getId();
325
            tableName = this.getName();
326
            // TODO: Buscar en gvsigd_resources el DAL antes de recrearlo.
327
            OnlineDownloader downloader = this.site.getDownloader();
328
            URL url = this.site.getURL("/api/v1/layers/" + tableId + "/description/");
329
            f = downloader.get(url);
330
            String description_s = FileUtils.readFileToString(f, StandardCharsets.UTF_8);
331
            description_json = Json.createObject(description_s);
332
            ftype = DALLocator.getDataManager().createFeatureType();
333
            for (JsonValue item0 : description_json.getJsonArray("content")) {
334
                item = (JsonObject) item0;
335
                String type_online = StringUtils.lowerCase(item.getString("type", null));
336
                type = DataTypes.UNKNOWN;
337
                size = 0;
338
                geomtype = null;
339
                if (type_online == null) {
340

    
341
                } else if ( StringUtils.equalsAnyIgnoreCase(type_online,"integer") ) {
342
                    type = DataTypes.INTEGER;
343
                } else if ( StringUtils.equalsAnyIgnoreCase(type_online,"bigint") ) {
344
                    type = DataTypes.LONG;
345
                } else if ( StringUtils.equalsAnyIgnoreCase(type_online,"numeric") ) {
346
                    precision = item.getInt("precision", 0);
347
                    scale = item.getInt("scale",0);
348
                    if( precision == 0 || (precision == 19 && scale==0 ) ) {
349
                        type = DataTypes.LONG;
350
                    } else {
351
                        type = DataTypes.DECIMAL;
352
                    }
353
                } else if ( StringUtils.equalsAnyIgnoreCase(type_online,"character varying") ) {
354
                    type = DataTypes.STRING;
355
                    size = item.getInt("length", 50);
356
                } else if ( StringUtils.equalsAnyIgnoreCase(type_online,"date") ) {
357
                    type = DataTypes.DATE;
358
                } else if ( StringUtils.containsIgnoreCase(type_online,"timestamp") ) {
359
                    type = DataTypes.TIMESTAMP;
360
                } else if ( StringUtils.equalsAnyIgnoreCase(type_online,"multipolygon") ) {
361
                    type = DataTypes.GEOMETRY;
362
                    geomtype = GeometryUtils.getGeometryType(Geometry.TYPES.MULTIPOLYGON, Geometry.SUBTYPES.GEOM2D);
363
                } else if ( StringUtils.equalsAnyIgnoreCase(type_online,"multilinestring") ) {
364
                    type = DataTypes.GEOMETRY;
365
                    geomtype = GeometryUtils.getGeometryType(Geometry.TYPES.MULTILINE, Geometry.SUBTYPES.GEOM2D);
366
                }                
367
                String name = item.getString("name", null);
368
                boolean nullable = BooleanUtils.toBoolean(item.getString("nullable", null));
369
                boolean pk = BooleanUtils.toBoolean(item.getString("pk", null));
370
                boolean mandatory = item.getBoolean("mandatory", false);
371
                String translate = item.getString("translate", null);
372
                EditableFeatureAttributeDescriptor fattr = ftype.add(name, type, size);
373
                fattr.setIsPrimaryKey(pk);
374
                fattr.setAllowNull(nullable);
375
                fattr.setLabel(translate);
376
                if( geomtype!=null ) {
377
                    fattr.setGeometryType(geomtype);
378
                    fattr.setSRS(this.getProjection());
379
                }
380
                if( type == DataTypes.DECIMAL ) {
381
                    fattr.setPrecision(precision);
382
                    fattr.setScale(scale);
383
                }
384
                switch(fattr.getName().toLowerCase()) {
385
                    case FEATUREMODIFIEDBY_FIELD_NAME:
386
                    case FEATURELASTMODIFICATION_FIELD_NAME:
387
                    case FEATUREDATE_FIELD_NAME:
388
                    case FEATUREVERSION_FIELD_NAME:
389
                        fattr.setHidden(true);
390
                        break;
391
                }
392
            }
393
            this.featureType = ftype;
394
            return this.featureType;
395
        } catch (Exception ex) {
396
            throw new RuntimeException("Can't get feature type for table '" + tableName + "' (id="  + tableId+")", ex);
397
        }
398
    }
399
    
400
    private long getCountElements(Envelope env) {
401
        LayerData layerData = this.getDataPage(env, 1, 0);
402
        return layerData.getTotalElemens();
403
    }    
404
    
405
    @Override
406
    public Iterator<JsonObject> getData(Envelope env, int pageSize, SimpleTaskStatus status) {
407
        return new LayerDataIterator(this, env, pageSize, status);
408
    }
409
    
410
    @Override
411
    public LayerData getDataPage(Envelope env, int pageSize, int page) {
412
        FileInputStream fis = null;
413
        try {
414
            OnlineDownloader downloader = this.site.getDownloader();
415
            URL url = this.site.getURL("/api/v1/layers/" + this.getId() + "/featurelist?"+
416
                    "minlat=" + String.format(Locale.ENGLISH,"%f", env.getMinimum(Geometry.DIMENSIONS.Y)) +
417
                    "&minlon=" + String.format(Locale.ENGLISH,"%f", env.getMinimum(Geometry.DIMENSIONS.X)) +
418
                    "&maxlat=" + String.format(Locale.ENGLISH,"%f", env.getMaximum(Geometry.DIMENSIONS.Y)) +
419
                    "&maxlon=" + String.format(Locale.ENGLISH,"%f", env.getMaximum(Geometry.DIMENSIONS.X)) +
420
                    "&epsg=" + this.getSRSCode()+
421
                    "&max=" + pageSize +
422
                    "&page=" + page
423
            );
424
            File f = downloader.get(url);
425
//            URL url = this.site.getURL("/api/v1/layers/" + this.getId() + "/featurelist");
426
//            JsonObjectBuilder postdata = Json.createObjectBuilder();
427
//            postdata.add("minlat", env.getMinimum(Geometry.DIMENSIONS.Y));
428
//            postdata.add("minlon", env.getMinimum(Geometry.DIMENSIONS.X));
429
//            postdata.add("maxlat", env.getMaximum(Geometry.DIMENSIONS.Y));
430
//            postdata.add("maxlon", env.getMaximum(Geometry.DIMENSIONS.X));
431
//            postdata.add("epsg", this.getSRSCode());
432
//            postdata.add("max", 10);//pageSize);
433
//            postdata.add("page", 1); //page);
434
//            File f = downloader.post_json(url, postdata.toString());
435
            if( f==null ) {
436
                return null;
437
            }
438
            fis = new FileInputStream(f);
439
            JsonObject json = Json.createObject(fis);
440
            if (json.containsKey("content")) {
441
                json = json.getJsonObject("content");
442
            }
443
            int totalfeatures = json.getInt("totalfeatures", -1);
444
            int lendata = json.getInt("lendata", -1);
445
            JsonArray features = json.getJsonArray("features");            
446
            return new LayerDataImpl(
447
                    lendata,
448
                    totalfeatures,
449
                    page,
450
                    features
451
            );
452
        } catch (Exception ex) {
453
            LOGGER.warn("Can't download data",ex);
454
            IOUtils.closeQuietly(fis);
455
            return null;
456
        }
457
    }
458
        
459
    @Override
460
    public IProjection getProjection() {
461
        if( this.projection == null ) {
462
            String srs = "unknown";
463
            try {
464
                srs = this.getSRS();
465
                this.projection = CRSFactory.getCRS(srs);
466
            } catch(Exception ex) {
467
                LOGGER.warn("Can't create projection from '"+srs+".",ex);
468
            }
469
        }
470
        return this.projection;
471
    }
472
    
473
    @Override
474
    public Envelope getEnvelope() {
475
        if (this.envelope == null) {
476
            String s = this.data.getString("native_extent", null);
477
            if (s == null) {
478
                return null;
479
            }
480
            String[] ss = StringUtils.split(s, ',');
481
            this.envelope = GeometryUtils.createEnvelope(
482
                    Double.parseDouble(ss[0]), 
483
                    Double.parseDouble(ss[1]), 
484
                    Double.parseDouble(ss[2]), 
485
                    Double.parseDouble(ss[3]), 
486
                    Geometry.SUBTYPES.GEOM2D
487
            );
488
        }
489
        return this.envelope;
490
    }
491
    
492
    @Override
493
    public int calculateTileSize(long maxElementsInTile, SimpleTaskStatus status) {
494
        OnlineLayerImpl layer = this;
495
        TilesCalculator.CalculatorData tileData = new TilesCalculator.CalculatorData() {
496
            @Override
497
            public Envelope getEnvelope() {
498
                return layer.getEnvelope();
499
            }
500

    
501
            @Override
502
            public double getWidth() {
503
                Envelope env = layer.getEnvelope();
504
                double w = env.getLength(Geometry.DIMENSIONS.X);
505
                return w;
506
            }
507

    
508
            @Override
509
            public double getHeight() {
510
                Envelope env = layer.getEnvelope();
511
                double h = env.getLength(Geometry.DIMENSIONS.Y);
512
                return h;
513
            }
514

    
515
            @Override
516
            public long getElements(Envelope envelope) {
517
                return layer.getCountElements(envelope);
518
            }
519
        };
520
        TilesCalculator tiles = new TilesCalculator();
521
        Dimension n = tiles.calculateCellSize(tileData, maxElementsInTile, status);
522
        return n.width;
523
    }
524

    
525
    public int update(Feature feature) {
526
        
527
    }
528
    
529
    public int insert(Feature feature) {
530
        
531
    }
532
    
533
    public int delete(Feature feature) {
534
        
535
    }
536
}