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 |
} |