Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / org.gvsig.arcims / src / org / gvsig / remoteclient / arcims / ArcImsProtFeatureHandler.java @ 32553

History | View | Annotate | Download (30.6 KB)

1 32319 vsanjaime
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2010 Prodevelop S.L. main development
26
 * http://www.prodevelop.es
27
 */
28
package org.gvsig.remoteclient.arcims;
29
30
import java.awt.geom.Rectangle2D;
31
import java.io.BufferedReader;
32
import java.io.File;
33
import java.io.FileInputStream;
34
import java.io.FileNotFoundException;
35
import java.io.FileReader;
36
import java.io.IOException;
37
import java.io.InputStream;
38
import java.io.InputStreamReader;
39
import java.io.Reader;
40
import java.io.UnsupportedEncodingException;
41
import java.net.MalformedURLException;
42
import java.net.URL;
43
import java.util.ArrayList;
44 32367 vsanjaime
import java.util.Date;
45 32319 vsanjaime
import java.util.Iterator;
46
import java.util.List;
47
import java.util.StringTokenizer;
48
import java.util.Vector;
49
50 32538 vsanjaime
import org.exolab.castor.xml.dtd.parser.ParseException;
51 32319 vsanjaime
import org.gvsig.fmap.geom.Geometry;
52 32367 vsanjaime
import org.gvsig.fmap.geom.GeometryLocator;
53
import org.gvsig.fmap.geom.GeometryManager;
54
import org.gvsig.fmap.geom.aggregate.impl.MultiPoint2D;
55
import org.gvsig.fmap.geom.exception.CreateGeometryException;
56 32319 vsanjaime
import org.gvsig.fmap.geom.primitive.GeneralPathX;
57 32367 vsanjaime
import org.gvsig.fmap.geom.primitive.Point;
58 32319 vsanjaime
import org.gvsig.remoteclient.arcims.exceptions.ArcImsException;
59
import org.gvsig.remoteclient.arcims.utils.ArcImsDownloadUtils;
60 32446 vsanjaime
import org.gvsig.remoteclient.arcims.utils.ArcImsFeature;
61 32319 vsanjaime
import org.gvsig.remoteclient.arcims.utils.FieldInformation;
62
import org.gvsig.remoteclient.arcims.utils.GetFeaturesTags;
63
import org.gvsig.remoteclient.arcims.utils.ServiceInfoTags;
64
import org.gvsig.remoteclient.arcims.utils.ServiceInformation;
65
import org.gvsig.remoteclient.arcims.utils.ServiceInformationLayerFeatures;
66
import org.gvsig.remoteclient.utils.BoundaryBox;
67
import org.kxml2.io.KXmlParser;
68
import org.slf4j.Logger;
69
import org.slf4j.LoggerFactory;
70 32367 vsanjaime
import org.xmlpull.v1.XmlPullParserException;
71 32319 vsanjaime
72
/**
73
 * @author jsanz
74
 *
75
 */
76
public class ArcImsProtFeatureHandler extends ArcImsProtocolHandler {
77
        private static boolean hasMore;
78
        private static int featCount;
79
        private static Logger logger = LoggerFactory
80
                        .getLogger(ArcImsProtFeatureHandler.class.getName());
81
82
        /**
83
         * Method to retrieve an ArrayList of features from an ArcIMS FeatureService
84
         *
85
         * @param status
86
         * @return ArrayList of IFeatures with geometries and Id's to attribute
87
         *         table
88
         * @throws ArcImsException
89
         */
90 32446 vsanjaime
        public List<List<ArcImsFeature>> getMap(ArcImsVectStatus status)
91
                        throws ArcImsException {
92 32319 vsanjaime
                logger.info("Start getMap");
93
94 32446 vsanjaime
                List<List<ArcImsFeature>> array = new ArrayList<List<ArcImsFeature>>();
95 32319 vsanjaime
96
                try {
97
                        /*
98
                         * Build the request
99
                         */
100
                        URL url = new URL(buildCapabilitiesRequest(status));
101
102
                        hasMore = true;
103
                        featCount = 1;
104
105
                        while (hasMore) {
106
                                /*
107
                                 * Build the proper ArcXML
108
                                 */
109
                                String request = ArcXMLFeatures.getFeatureLayerRequest(status,
110
                                                featCount);
111
112
                                if (status.verbose) {
113
                                        System.err.println(request);
114
                                }
115
116
                                /*
117
                                 * Request the reader
118
                                 */
119
                                logger.info("Start features downloading");
120
121
                                File f = ArcImsDownloadUtils.doRequestPost(url, request,
122
                                                "getFeatures.xml");
123
                                logger.info("End features downloading");
124
125
                                /*
126
                                 * Parse response and add geometries to the general Array
127
                                 */
128 32538 vsanjaime
                                String layerId = (String) status.getLayersIdsSelected().get(0);
129 32319 vsanjaime
130
                                // Deal with UTF-8
131
                                Reader reader = null;
132
                                FileInputStream fis = new FileInputStream(f);
133
                                InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
134
                                BufferedReader br = new BufferedReader(isr);
135
                                reader = br;
136
137
                                logger.debug("Start features with attributes parsing");
138 32446 vsanjaime
                                List<ArcImsFeature> feats = this.getFeatures(reader, status
139
                                                .getServiceInfo(), layerId, status.getSubfields(), 1);
140
                                array.add(feats);
141 32319 vsanjaime
                                logger.debug("End features with attributes parsing");
142
                        }
143
144
                        hasMore = true;
145
                        featCount = 1;
146
                } catch (MalformedURLException e) {
147
                        logger.error(e.getMessage(), e);
148
                        throw new ArcImsException("arcims_server_error");
149
                } catch (FileNotFoundException e) {
150
                        logger.error(e.getMessage(), e);
151
                        throw new ArcImsException("arcims_server_error");
152
                } catch (UnsupportedEncodingException e) {
153
                        logger.error(e.getMessage(), e);
154
                }
155
156
                logger.debug("End getMap");
157
158
                return array;
159
        }
160
161
        /**
162
         * Parse the XML data retrieved from ArcIMS GET_FEATURES request to get a
163
         * set of Features if withGeometries is true or an ArrayList of Value[] if
164
         * this boolean is false
165
         *
166
         * @param Reader
167
         *            Stream to parse
168
         * @param si
169
         *            ServiceInformation with metadata
170
         * @param layerId
171
         *            Layer retrieved
172
         * @param subfields
173
         *            Subfields retrieved
174
         * @param withGeometries
175
         *            Will geometries be parsed?: 0=no 1=yes 2=evelopes
176
         * @return ArrayList of IFeatures or Value[]
177
         * @throws ArcImsException
178
         */
179 32446 vsanjaime
        private List<ArcImsFeature> getFeatures(Reader lector,
180
                        ServiceInformation si, String layerId, String[] subfields,
181
                        int withGeometries) throws ArcImsException {
182 32367 vsanjaime
183
                // fill features map
184 32319 vsanjaime
                FieldInformation fi = null;
185
                ServiceInformationLayerFeatures sil = (ServiceInformationLayerFeatures) si
186
                                .getLayerById(layerId);
187
188
                /*
189
                 * Prepare a Value array to store every FEATURE tag information
190
                 */
191 32367 vsanjaime
                Vector<FieldInformation> fieldsInfo = sil.getFieldsInfo();
192 32319 vsanjaime
193
                // If flag == true, throw an Exception (no layerId found)
194
                if (fieldsInfo == null) {
195
                        throw new ArcImsException("arcims_no_features");
196
                }
197
198
                // We will store names and types in a hashmap
199 32367 vsanjaime
                List<FieldInformation> fieldsInfoA = new ArrayList<FieldInformation>();
200 32319 vsanjaime
201
                /*
202
                 * If subfields[0] is equal to #ALL we add the entire vector into the
203
                 * Hasmap
204
                 */
205
                if (subfields[0].equals("#ALL#")) {
206
                        for (int i = 0; i < fieldsInfo.size(); i++) {
207 32367 vsanjaime
                                fi = fieldsInfo.get(i);
208 32319 vsanjaime
                                fieldsInfoA.add(fi);
209
                        }
210
                } else {
211
                        for (int i = 0; i < subfields.length; i++) {
212
                                fi = null;
213
                                fi = sil.getFieldInformation(subfields[i]);
214
215
                                if (fi != null) {
216
                                        fieldsInfoA.add(fi);
217
                                }
218
                        }
219
                }
220
221
                /*
222
                 * Get the separators
223
                 */
224
                String delCoords = si.getSeparators().getCs();
225
                String delTuple = si.getSeparators().getTs();
226
                char delDec = si.getSeparators().getDs();
227
228
                /*
229
                 * ArrayList with features
230
                 */
231 32446 vsanjaime
                List<ArcImsFeature> features = new ArrayList<ArcImsFeature>();
232 32319 vsanjaime
233
                /*
234
                 * Start parsing
235
                 */
236
                int tag;
237 32367 vsanjaime
                KXmlParser kxmlParser = new KXmlParser();
238 32319 vsanjaime
239
                Geometry geom = null;
240 32553 vsanjaime
                //Object[] values = new Object[fieldsInfoA.size()];
241 32367 vsanjaime
                // Value[] values = new Value[fieldsInfoA.size()];
242 32446 vsanjaime
                int[] position = new int[fieldsInfoA.size()];
243
244
                // Initialize position array
245
                for (int i = 0; i < position.length; i++)
246
                        position[i] = -1;
247
248
                // long timeFeat = 0;
249
                // long timeGeom = 0;
250
                // long timeTemp = 0;
251
                try {
252
                        kxmlParser.setInput(lector);
253
                        kxmlParser.nextTag();
254
255
                        if (kxmlParser.getEventType() != KXmlParser.END_DOCUMENT) {
256
                                kxmlParser.require(KXmlParser.START_TAG, null,
257
                                                ServiceInfoTags.tARCXML);
258
                                tag = kxmlParser.nextTag();
259
260
                                while (tag != KXmlParser.END_DOCUMENT) {
261 32538 vsanjaime
262
                                        ArcImsFeature afeat = new ArcImsFeature();
263
264 32446 vsanjaime
                                        switch (tag) {
265
                                        case KXmlParser.START_TAG:
266
267
                                                if (kxmlParser.getName().compareTo(
268
                                                                GetFeaturesTags.FEATURE) == 0) {
269
                                                        /*
270
                                                         * parse FEATURES' tag
271
                                                         */
272
273
                                                        // FIRST ENVELOPE TAG (We hope that ENVELOPE will
274
                                                        // ALLWAYS be returned at first...)
275
                                                        if (withGeometries == 2) {
276
                                                                // timeTemp = System.currentTimeMillis();
277
                                                                geom = parseEnvelopeFromFeatureTag(kxmlParser,
278
                                                                                delDec);
279 32538 vsanjaime
                                                                afeat.putGeometry(geom);
280 32446 vsanjaime
                                                        }
281
282
                                                        // SECOND FIELDS TAG
283
                                                        // timeTemp = System.currentTimeMillis();
284 32538 vsanjaime
                                                        afeat = parseValuesFromFeatureTag(kxmlParser, // the
285 32446 vsanjaime
                                                                        // kxml
286
                                                                        // parser
287
                                                                        fieldsInfoA, // Hashmap with names and
288
                                                                        // FieldInformation objects)
289
                                                                        delDec, // the separators
290 32538 vsanjaime
                                                                        position, // the relative positions of
291 32446 vsanjaime
                                                        // returned values
292 32538 vsanjaime
                                                                        afeat
293 32446 vsanjaime
                                                        );
294
295
                                                        // timeFeat += System.currentTimeMillis() -
296
                                                        // timeTemp;
297
298
                                                        // If geometries are neede we add to the ArrayList
299
                                                        // the Ifeature
300
                                                        if (withGeometries == 1) {
301
                                                                // THIRD GEOMETRIES
302
                                                                // timeTemp = System.currentTimeMillis();
303
                                                                geom = parseGeomFromFeatureTag(kxmlParser, // the
304
                                                                                // kxml
305
                                                                                // parser
306
                                                                                delTuple, delCoords, delDec // the
307
                                                                // separators
308 32538 vsanjaime
309 32446 vsanjaime
                                                                );
310 32538 vsanjaime
                                                                afeat.putGeometry(geom);
311 32446 vsanjaime
312
                                                                // timeGeom += System.currentTimeMillis() -
313
                                                                // timeTemp;
314
                                                        }
315
316 32538 vsanjaime
                                                        // // If some geometry is created, we add a IFeature
317
                                                        // // into features ArrayList
318
                                                        // if (withGeometries > 0) {
319
                                                        // features.add(new ArcImsFeature(geom, values));
320
                                                        // }
321
                                                        // // Else we only need the Value[] array
322
                                                        // else {
323
                                                        // features.add(new ArcImsFeature(values));
324
                                                        // }
325 32446 vsanjaime
                                                } else if (kxmlParser.getName().compareTo(
326
                                                                GetFeaturesTags.FEATURECOUNT) == 0) {
327
                                                        String value = new String();
328
329
                                                        // Get the feature count
330
                                                        value = kxmlParser.getAttributeValue("",
331
                                                                        GetFeaturesTags.COUNT);
332
333
                                                        Integer intFeatCount = new Integer(value);
334
                                                        featCount += intFeatCount.intValue();
335
336
                                                        // Get the hasmore boolean
337
                                                        value = kxmlParser.getAttributeValue("",
338
                                                                        GetFeaturesTags.HASMORE);
339
340
                                                        Boolean boHasMore = new Boolean(value);
341
                                                        hasMore = boHasMore.booleanValue();
342
                                                } else if (kxmlParser.getName().compareTo(
343
                                                                ServiceInfoTags.tERROR) == 0) {
344
                                                        logger.error("Error parsing GET_FEATURES:\r\n"
345
                                                                        + kxmlParser.nextText());
346
                                                        throw new ArcImsException("arcims_server_error");
347
                                                }
348
349
                                                break;
350
351
                                        case KXmlParser.END_TAG:
352
                                                break;
353
354
                                        case KXmlParser.TEXT:
355
                                                break;
356
                                        }
357 32538 vsanjaime
                                        if(afeat != null){
358
                                                features.add(afeat);
359
                                        }
360 32446 vsanjaime
                                        tag = kxmlParser.next();
361
                                }
362
363
                                kxmlParser.require(KXmlParser.END_DOCUMENT, null, null);
364
                        }
365
                }
366
367
                catch (XmlPullParserException parser_ex) {
368
                        logger.error(parser_ex.getMessage(), parser_ex);
369
                        throw new ArcImsException("arcims_no_features");
370
                } catch (IOException ioe) {
371
                        logger.error(ioe.getMessage(), ioe);
372
                        throw new ArcImsException("arcims_no_features");
373
                } catch (CreateGeometryException e) {
374
                        logger.error(e.getMessage(), e);
375
                        throw new ArcImsException("arcims_no_features");
376
                }
377
378
                return features;
379
380 32319 vsanjaime
        }
381
382
        /**
383
         * Returns an IGeometry with a line between corners of an ENVELOPE
384
         *
385
         * @param parser
386
         * @param delDec
387
         * @return
388
         * @throws XmlPullParserException
389
         * @throws IOException
390
         */
391
        private Geometry parseEnvelopeFromFeatureTag(KXmlParser parser, char delDec)
392
                        throws XmlPullParserException, IOException {
393
                int currentTag;
394
                boolean end = false;
395
396
                BoundaryBox bb = null;
397
398
                // parser.require(KXmlParser.START_TAG,null,GetFeaturesTags.FIELDS);
399
                currentTag = parser.next();
400
401
                while (!end) {
402
                        switch (currentTag) {
403
                        case KXmlParser.START_TAG:
404
405
                                if (parser.getName().equals(ServiceInfoTags.tENVELOPE)) {
406
                                        bb = super.parseEnvelope(parser, delDec);
407
                                        end = true;
408
                                }
409
410
                                break;
411
412
                        case KXmlParser.END_TAG:
413
414
                                if (parser.getName().equals(GetFeaturesTags.FIELDS)) {
415
                                        end = true;
416
                                }
417
418
                                break;
419
420
                        case KXmlParser.TEXT:
421
                                break;
422
                        }
423
424
                        if (!end) {
425
                                currentTag = parser.next();
426
                        }
427
                }
428
429
                // If BoundaryBox object has been created, we can convert it into a
430
                // IGeometry (polyline).
431
                if (bb != null) {
432
                        GeneralPathX polyline = new GeneralPathX(GeneralPathX.WIND_EVEN_ODD);
433
434
                        polyline.moveTo(bb.getXmin(), bb.getYmin());
435
                        polyline.lineTo(bb.getXmax(), bb.getYmax());
436
437 32367 vsanjaime
                        GeometryManager geomManager = GeometryLocator.getGeometryManager();
438
                        Geometry curve = null;
439
                        try {
440
                                curve = geomManager.createCurve(polyline,
441
                                                Geometry.SUBTYPES.GEOM2D);
442
                        } catch (CreateGeometryException e) {
443
                                logger.error("Error creating curve", e);
444
                                return null;
445
                        }
446
                        return curve;
447 32319 vsanjaime
                } else {
448
                        return null;
449
                }
450 32367 vsanjaime
451 32319 vsanjaime
        }
452
453
        /**
454
         * @param kxmlParser
455
         * @param fieldsInfoH
456
         * @param delDec
457
         * @param position
458
         * @return
459
         * @throws IOException
460
         * @throws XmlPullParserException
461 32367 vsanjaime
         * @throws IOException
462
         * @throws XmlPullParserException
463 32319 vsanjaime
         * @throws ArcImsException
464 32367 vsanjaime
         * @throws ArcImsException
465 32319 vsanjaime
         * @throws ParseException
466
         */
467 32538 vsanjaime
        private ArcImsFeature parseValuesFromFeatureTag(KXmlParser parser,
468
                        List<FieldInformation> fieldsInfoA, char delDec, int[] position, ArcImsFeature afeat )
469 32367 vsanjaime
                        throws XmlPullParserException, IOException, ArcImsException {
470
471 32319 vsanjaime
                int currentTag;
472
                boolean end = false;
473
                int f = 0;
474
                String att;
475 32367 vsanjaime
                String text;
476 32319 vsanjaime
                int type;
477
478 32538 vsanjaime
                //Object[] values = new Object[fieldsInfoA.size()];
479 32319 vsanjaime
480
                currentTag = parser.next();
481
482
                while (!end) {
483
                        switch (currentTag) {
484
                        case KXmlParser.START_TAG:
485
486
                                if (parser.getName().equals(GetFeaturesTags.FIELD)) {
487
                                        att = parser.getAttributeValue("", GetFeaturesTags.NAME);
488 32367 vsanjaime
                                        text = parser.getAttributeValue("", GetFeaturesTags.VALUE);
489 32319 vsanjaime
490
                                        /*
491
                                         * As NAME is known, we need to get the position of that
492
                                         * attribute into the ArrayList of fieldInformation objects
493
                                         */
494
                                        if (position[f] == -1) {
495 32538 vsanjaime
                                                position[f] = getPosition(fieldsInfoA.iterator(), att);
496 32319 vsanjaime
                                        }
497
498
                                        if (position[f] == -1) {
499
                                                logger.error("Attribute not found at Metadata");
500
                                                throw new ArcImsException(
501
                                                                "Attribute not found at Metadata");
502
                                        }
503
504
                                        // This way we can create a NullValue
505 32367 vsanjaime
                                        if (text.equals("")) {
506
                                                text = null;
507 32319 vsanjaime
                                        }
508
509
                                        /*
510
                                         * At this point we know wat FieldInfo of the ArrayList we
511
                                         * have to retrieve
512
                                         */
513
                                        type = ((FieldInformation) fieldsInfoA.get(position[f]))
514
                                                        .getType();
515
516
                                        // Add the Value into the correct position
517 32367 vsanjaime
                                        if (text == null) {
518 32538 vsanjaime
                                                String fieldName = fieldsInfoA.get(position[f]).getName();
519 32553 vsanjaime
                                                afeat.put(fieldName,null);
520 32367 vsanjaime
                                        } else {
521 32538 vsanjaime
                                                String fieldName = fieldsInfoA.get(position[f]).getName();
522 32367 vsanjaime
                                                switch (type) {
523
                                                case FieldInformation.BOOLEAN:
524 32538 vsanjaime
                                                        afeat.put(fieldName,new Boolean(text));
525 32367 vsanjaime
                                                        f++;
526
                                                        break;
527
                                                case FieldInformation.SHAPE:
528
                                                case FieldInformation.STRING:
529 32538 vsanjaime
                                                        afeat.put(fieldName, new String(text));
530 32367 vsanjaime
                                                        f++;
531
                                                        break;
532
                                                case FieldInformation.DATE:
533 32538 vsanjaime
                                                        afeat.put(fieldName, new Date(Long.parseLong(text)));
534 32367 vsanjaime
                                                        f++;
535
                                                        break;
536
                                                case FieldInformation.FLOAT:
537
                                                        String textfloat = text.replace(delDec, '.');
538 32538 vsanjaime
                                                        afeat.put(fieldName, new Float(textfloat));
539 32367 vsanjaime
                                                        f++;
540
                                                        break;
541
                                                case FieldInformation.DOUBLE:
542
                                                        String textdouble = text.replace(delDec, '.');
543 32538 vsanjaime
                                                        afeat.put(fieldName, new Double(textdouble));
544 32367 vsanjaime
                                                        f++;
545
                                                        break;
546
                                                case FieldInformation.SMALLINT:
547 32538 vsanjaime
                                                        afeat.put(fieldName, new Short(text));
548 32367 vsanjaime
                                                        f++;
549
                                                        break;
550
                                                case FieldInformation.BIGINT:
551 32538 vsanjaime
                                                        afeat.put(fieldName, new Long(text));
552 32367 vsanjaime
                                                        f++;
553
                                                        break;
554
                                                case FieldInformation.ID:
555 32553 vsanjaime
                                                        afeat.put(fieldName, new String(text));
556
                                                        afeat.setFieldPK(fieldName);
557
                                                        f++;
558
                                                        break;
559 32367 vsanjaime
                                                case FieldInformation.INTEGER:
560 32538 vsanjaime
                                                        afeat.put(fieldName, new Integer(text));
561 32367 vsanjaime
                                                        f++;
562
                                                        break;
563
                                                default:
564 32538 vsanjaime
                                                        afeat.put(fieldName, new String(text));
565 32367 vsanjaime
                                                        f++;
566
                                                }
567
                                        }
568 32319 vsanjaime
                                }
569
570
                                break;
571
572
                        case KXmlParser.END_TAG:
573
574
                                if (parser.getName().equals(GetFeaturesTags.FIELDS)) {
575
                                        end = true;
576
                                }
577
578
                                break;
579
580
                        case KXmlParser.TEXT:
581
                                break;
582
                        }
583
584
                        if (!end) {
585
                                currentTag = parser.next();
586
                        }
587
                }
588
589 32538 vsanjaime
                return afeat;
590 32367 vsanjaime
591 32319 vsanjaime
        }
592
593
        /**
594
         * Method to get the position of an attribute into the subfields array
595
         *
596
         * @param fieldsInfoA
597
         * @param att
598
         * @return
599
         */
600
        private int getPosition(Iterator it, String att) {
601
                int res = 0;
602
                FieldInformation fi;
603
604
                while (it.hasNext()) {
605
                        fi = (FieldInformation) it.next();
606
607
                        if (fi.getName().equals(att)) {
608
                                return res;
609
                        }
610
611
                        res++;
612
                }
613
614
                // If no integer has returned at this point we return a -1
615
                return -1;
616
        }
617
618
        /**
619
         * Parses the Feature Tag to get a IFeature
620
         *
621
         * @param KxmlParser
622
         *            with the FEATURE tag
623
         * @param Value
624
         *            array with the correct subtypes to store FIELDS data
625
         * @param String
626
         *            array with the correct fields names to retrieve
627
         * @param String
628
         *            with the tuple separator
629
         * @param String
630
         *            with the coordinates separator
631
         * @param Char
632
         *            with the decimal separator
633
         * @return @see com.hardcode.gdbms.engine.values.Value.IFeature
634
         * @throws IOException
635
         * @throws XmlPullParserException
636 32367 vsanjaime
         * @throws IOException
637
         * @throws XmlPullParserException
638
         * @throws CreateGeometryException
639 32319 vsanjaime
         * @throws ArcImsException
640 32367 vsanjaime
         * @throws CreateGeometryException
641
         * @throws ArcImsException
642 32319 vsanjaime
         */
643
        private Geometry parseGeomFromFeatureTag(KXmlParser parser,
644 32367 vsanjaime
                        String delTuple, String delCoords, char delDec)
645
                        throws XmlPullParserException, IOException,
646
                        CreateGeometryException, ArcImsException {
647
648
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
649 32319 vsanjaime
                int currentTag;
650
                boolean end = false;
651
                Geometry geom = null;
652
                currentTag = parser.next();
653
654
                while (!end) {
655
                        String featType = parser.getName();
656
657
                        switch (currentTag) {
658
                        case KXmlParser.START_TAG:
659 32367 vsanjaime
                                // //////////////////////////
660
                                // geometry type MULTIPOINT
661
                                // //////////////////////////
662 32319 vsanjaime
                                if (featType.equals(GetFeaturesTags.MULTIPOINT)) {
663
                                        // Go to COORDS tag
664
                                        parser.nextTag();
665
666
                                        if (parser.getName().equals(GetFeaturesTags.COORDS)) {
667
                                                // Create a tokenizer with the tuples
668
                                                String strPoints = parser.nextText();
669
670
                                                // Get the points from COORDS string
671 32367 vsanjaime
                                                List<Point> points = parseCoords(strPoints, delTuple,
672 32319 vsanjaime
                                                                delCoords, delDec);
673
674 32367 vsanjaime
                                                geom = geomManager.create(Geometry.TYPES.MULTIPOINT,
675
                                                                Geometry.SUBTYPES.GEOM2D);
676
                                                MultiPoint2D mpoint = (MultiPoint2D) geom;
677
                                                for (Point point : points) {
678
                                                        mpoint.addPoint(point);
679 32319 vsanjaime
                                                }
680
                                        } else {
681
                                                logger.error("Error parsing MULTIPOINT tag");
682
                                                throw new ArcImsException("arcims_features_error");
683
                                        }
684 32367 vsanjaime
                                }
685
                                // ////////////////////////////////////////////
686
                                // POLYLINE or POLYGON
687
                                // ////////////////////////////////////////////
688
                                else if (featType.equals(GetFeaturesTags.POLYLINE)
689 32319 vsanjaime
                                                || featType.equals(GetFeaturesTags.POLYGON)) {
690
                                        // Parse while parser doesn't found </FEATURES> tag
691
                                        // The GeneralPath to store the different paths
692
                                        GeneralPathX polyline = new GeneralPathX(
693
                                                        GeneralPathX.WIND_EVEN_ODD);
694
                                        boolean endpol = false;
695
696
                                        while (!endpol) {
697
                                                switch (currentTag) {
698
                                                case KXmlParser.START_TAG:
699
700
                                                        if (parser.getName().equals(GetFeaturesTags.COORDS)) {
701
                                                                // Create a tokenizer with the tuples
702
                                                                String strPoints = parser.nextText();
703
704
                                                                // Get the points (Point2D) from COORDS string
705 32367 vsanjaime
                                                                List<Point> points = parseCoords(strPoints,
706 32319 vsanjaime
                                                                                delTuple, delCoords, delDec);
707
708 32446 vsanjaime
                                                                Iterator<Point> it = points.iterator();
709 32367 vsanjaime
                                                                Point point;
710 32319 vsanjaime
711
                                                                // First we MOVE to the first point of the path
712 32367 vsanjaime
                                                                point = (Point) it.next();
713 32319 vsanjaime
                                                                polyline.moveTo(point.getX(), point.getY());
714
715
                                                                // And now we can LINE to the rest of the points
716
                                                                // of the path
717
                                                                while (it.hasNext()) {
718 32367 vsanjaime
                                                                        point = (Point) it.next();
719 32319 vsanjaime
                                                                        polyline.lineTo(point.getX(), point.getY());
720
                                                                }
721
                                                        }
722
723
                                                        break;
724
725
                                                case KXmlParser.END_TAG:
726
727
                                                        if (parser.getName().equals(featType)) {
728
                                                                endpol = true;
729
                                                        }
730
731
                                                        break;
732
733
                                                case KXmlParser.TEXT:
734
                                                        break;
735
                                                }
736
737
                                                if (!endpol) {
738
                                                        currentTag = parser.next();
739
                                                }
740
                                        }
741
742
                                        if (featType.equals(GetFeaturesTags.POLYLINE)) {
743 32367 vsanjaime
                                                geom = geomManager.createMultiCurve(polyline,
744
                                                                Geometry.SUBTYPES.GEOM2D);
745 32319 vsanjaime
                                        } else if (featType.equals(GetFeaturesTags.POLYGON)) {
746 32367 vsanjaime
                                                geom = geomManager.createMultiSurface(polyline,
747
                                                                Geometry.SUBTYPES.GEOM2D);
748 32319 vsanjaime
                                        }
749
                                }
750
751
                                break;
752
753
                        case KXmlParser.END_TAG:
754
755
                                if (parser.getName().compareTo(GetFeaturesTags.FEATURE) == 0) {
756
                                        end = true;
757
                                }
758
759
                                break;
760
761
                        case KXmlParser.TEXT:
762
                                break;
763
                        }
764
765
                        if (!end) {
766
                                currentTag = parser.next();
767
                        }
768
                }
769
770
                return geom;
771
        }
772
773
        /**
774
         * Private method that parses a COORDS tag to return an ArrayList of
775
         * Point2D.Double objects
776
         *
777
         * @param strCoords
778
         * @param delTuple
779
         * @param delCoords
780
         * @param delDec
781
         * @return
782 32367 vsanjaime
         * @throws CreateGeometryException
783 32319 vsanjaime
         */
784 32367 vsanjaime
        private List<Point> parseCoords(String strCoords, String delTuple,
785
                        String delCoords, char delDec) throws CreateGeometryException {
786
787
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
788
                List<Point> points = new ArrayList<Point>();
789 32319 vsanjaime
                String tupla = new String();
790
                String[] tuplaPart;
791
                Double x;
792
                Double y;
793
794
                /*
795
                 * Replaces Decimal Separator to convert coords to suitable doubles.
796
                 *
797
                 * Maybe it will have a better performance if we insert this replace
798
                 * into the while
799
                 */
800
                if (delDec != '.') {
801
                        strCoords = strCoords.replace(delDec, '.');
802
                }
803
804
                // Creates a tokenizer to run over the string
805
                StringTokenizer tuplas = new StringTokenizer(strCoords, delTuple, false);
806
807
                // Get ArrayLists collections with X's and Y's
808
                while (tuplas.hasMoreTokens()) {
809
                        // tupla = tuplas.nextToken().replace(delDec,'.');
810
                        tupla = tuplas.nextToken();
811
                        tuplaPart = tupla.split(delCoords);
812
                        x = new Double(tuplaPart[0]);
813
                        y = new Double(tuplaPart[1]);
814
815 32367 vsanjaime
                        Point pto = geomManager.createPoint(x.doubleValue(), y
816
                                        .doubleValue(), Geometry.SUBTYPES.GEOM2D);
817
                        points.add(pto);
818 32319 vsanjaime
                }
819
820 32367 vsanjaime
                // Return an array of Point objects
821 32319 vsanjaime
                return points;
822
        }
823
824
        /**
825
         * @param status
826
         * @return
827
         * @throws ArcImsException
828
         */
829
        public Rectangle2D getLayerExtent(ArcImsVectStatus status)
830
                        throws ArcImsException {
831
                Rectangle2D envelope = null;
832 32538 vsanjaime
                String layerId = (String) status.getLayersIdsSelected().get(0);
833 32319 vsanjaime
834
                // logger.info("Getting Vectorial Layer Extent (" + status.getl)
835
                ServiceInformation si = status.getServiceInfo();
836
                String ini_srs = ServiceInfoTags.vINI_SRS;
837
838
                String srsView = status.getSrs().substring(ini_srs.length()).trim();
839
                String srsServ = si.getFeaturecoordsys();
840
                boolean srsAssumed = si.isSrsAssumed();
841
842
                if (srsAssumed || (srsView.equals(srsServ))) {
843
                        BoundaryBox bb = si.getLayerById(layerId).getEnvelope();
844
845
                        /*
846
                         * At the end, we convert the BoundaryBox to a Rectangle2D
847
                         */
848
                        envelope = new Rectangle2D.Double();
849
850
                        envelope.setFrameFromDiagonal(bb.getXmin(), bb.getYmin(), bb
851
                                        .getXmax(), bb.getYmax());
852
853
                        return envelope;
854
                }
855
856
                /*
857
                 * If SRS of View and Service are different, we do a custom request to
858
                 * retrieve the global envelope of the layer
859
                 */
860
                try {
861
                        /*
862
                         * Build the request
863
                         */
864
                        URL url;
865
                        url = new URL(buildCapabilitiesRequest(status));
866
867
                        /*
868
                         * Build the proper ArcXML
869
                         */
870
                        String request = ArcXMLFeatures.getLayerExtentRequest(status);
871
872
                        if (status.verbose) {
873
                                System.err.println(request);
874
                        }
875
876
                        /*
877
                         * Request the envelope
878
                         */
879
                        File response;
880
                        response = ArcImsDownloadUtils.doRequestPost(url, request,
881
                                        "getLayerExtent.xml");
882
883
                        /*
884
                         * Parse response and return a Rectangle2D
885
                         */
886
                        char ds = si.getSeparators().getDs();
887
                        envelope = parseEnvelopeTag(new FileReader(response), ds);
888
                } catch (MalformedURLException e) {
889
                        logger.error(e.getMessage(), e);
890
                        throw new ArcImsException("arcims_server_error");
891
                } catch (FileNotFoundException e) {
892
                        logger.error(e.getMessage(), e);
893
                        throw new ArcImsException("arcims_server_error");
894
                }
895
896
                return envelope;
897
        }
898
899
        /**
900
         * Retrieves an ArrayList of Value arrays. The query can be filtered by a
901
         * WHERE clause or an envelope. Only subfields passed will be retrieved
902
         *
903
         * @param status
904
         * @param subfields
905
         * @param where
906
         * @param envelope
907
         * @return
908
         * @throws ArcImsException
909
         */
910 32446 vsanjaime
        public List<List<ArcImsFeature>> getAttributes(ArcImsVectStatus status,
911
                        String[] subfields, String where, Rectangle2D envelope)
912
                        throws ArcImsException {
913 32367 vsanjaime
914 32319 vsanjaime
                logger.info("Start getAttributes");
915
916 32446 vsanjaime
                List<List<ArcImsFeature>> features = new ArrayList<List<ArcImsFeature>>();
917 32319 vsanjaime
918
                // Clone the status and set temporal subfields and where clause
919
                ArcImsVectStatus statusCloned = status;
920
921
                String[] subTemp = status.getSubfields();
922
                String whereTemp = status.getWhere();
923 32367 vsanjaime
                Rectangle2D rectTemp = status.getEnvelopeRect();
924 32319 vsanjaime
925
                statusCloned.setSubfields(subfields);
926
                statusCloned.setWhere(where);
927
                statusCloned.setEnvelope(envelope);
928
929
                try {
930
                        /*
931
                         * Build the request
932
                         */
933
                        URL url;
934
                        url = new URL(buildCapabilitiesRequest(statusCloned));
935
936
                        hasMore = true;
937
                        featCount = 0;
938
939
                        while (hasMore) {
940
                                /*
941
                                 * Build the proper ArcXML
942
                                 */
943
                                String request = ArcXMLFeatures.getAttributesRequest(
944
                                                statusCloned, featCount);
945
946
                                if (status.verbose) {
947
                                        System.err.println(request);
948
                                }
949
950
                                // The attributes come from ArcIMS in ASCII/cp1252 encoding
951
                                boolean withUTF = false;
952
953
                                // Don't download the file, pass the data directly from the
954
                                // connection
955
                                boolean withFile = false;
956
957
                                /*
958
                                 * Get an InputStream from File or directly from the connection
959
                                 */
960
                                InputStream is = null;
961
962
                                if (withFile) {
963
                                        File f = ArcImsDownloadUtils.doRequestPost(url, request,
964
                                                        "getAttributes.xml");
965
966
                                        try {
967
                                                is = new FileInputStream(f);
968
                                        } catch (FileNotFoundException e) {
969
                                                logger.error(e.getMessage(), e);
970
                                        }
971
                                } else {
972
                                        is = ArcImsDownloadUtils.getRemoteIS(url, request);
973
                                }
974
975
                                InputStreamReader isr = null;
976
977
                                if (withUTF) {
978
                                        // Deal with UTF-8
979
                                        try {
980
                                                isr = new InputStreamReader(is, "UTF-8");
981
                                        } catch (UnsupportedEncodingException e) {
982
                                                logger.error(e.getMessage(), e);
983
                                        }
984
                                } else {
985
                                        // No deal with UTF-8
986
                                        isr = new InputStreamReader(is);
987
                                }
988
989
                                /*
990
                                 * Finally, we can create a BufferedReader from the
991
                                 * InputStreamReader
992
                                 */
993
                                BufferedReader br = new BufferedReader(isr);
994
995
                                /*
996
                                 * Parse response and return a Rectangle2D
997
                                 */
998 32538 vsanjaime
                                String layerId = (String) statusCloned.getLayersIdsSelected().get(0);
999 32319 vsanjaime
                                logger.debug("Start attributes downloading and parsing ("
1000
                                                + featCount + ") ids retrieved");
1001 32446 vsanjaime
                                features.add(getFeatures(br, statusCloned.getServiceInfo(),
1002 32367 vsanjaime
                                                layerId, statusCloned.getSubfields(), 0));
1003 32319 vsanjaime
                                logger.debug("End attributes downloading and parsing");
1004
                        }
1005
1006
                        hasMore = true;
1007
                        featCount = 0;
1008
                } catch (MalformedURLException e) {
1009
                        logger.error(e.getMessage(), e);
1010
                        throw new ArcImsException("arcims_server_error");
1011
                } catch (ArcImsException e) {
1012
                        logger.error(e.getMessage(), e);
1013
                        throw new ArcImsException("arcims_server_error");
1014
                } finally {
1015
                        status.setSubfields(subTemp);
1016
                        status.setWhere(whereTemp);
1017
                        status.setEnvelope(rectTemp);
1018
                }
1019
1020
                logger.debug("End attributes retrieving");
1021
1022 32446 vsanjaime
                return features;
1023 32319 vsanjaime
        }
1024
1025
        /**
1026
         * Retrieves an ArrayList of I by some IDs. The geometry returned is the
1027
         * envelope of the feature requested. The query can be filtered by a WHERE
1028
         * clause or an envelope. Only subfields passed will be retrieved
1029
         *
1030
         * @param status
1031
         * @param subfields
1032
         * @param where
1033
         * @param envelope
1034
         * @return
1035
         * @throws ArcImsException
1036
         */
1037 32446 vsanjaime
        public List<List<ArcImsFeature>> getAttributesWithEnvelope(
1038
                        ArcImsVectStatus status, String[] subfields, String where,
1039
                        Rectangle2D envelope) throws ArcImsException {
1040 32367 vsanjaime
1041 32319 vsanjaime
                logger.info("Start getAttributesWihtEnvelope");
1042
1043 32446 vsanjaime
                List<List<ArcImsFeature>> features = new ArrayList<List<ArcImsFeature>>();
1044 32319 vsanjaime
1045
                // Clone the status and set temporal subfields and where clause
1046
                ArcImsVectStatus statusCloned = status;
1047
1048
                String[] subTemp = status.getSubfields();
1049
                String whereTemp = status.getWhere();
1050 32367 vsanjaime
                Rectangle2D rectTemp = status.getEnvelopeRect();
1051 32319 vsanjaime
1052
                statusCloned.setSubfields(subfields);
1053
                statusCloned.setWhere(where);
1054
                statusCloned.setEnvelope(envelope);
1055
1056
                try {
1057
                        /*
1058
                         * Build the request
1059
                         */
1060
                        URL url;
1061
                        url = new URL(buildCapabilitiesRequest(statusCloned));
1062
1063
                        hasMore = true;
1064
                        featCount = 0;
1065
1066
                        while (hasMore) {
1067
                                /*
1068
                                 * Build the proper ArcXML
1069
                                 */
1070
                                String request = ArcXMLFeatures.getAttributesRequest(
1071
                                                statusCloned, featCount);
1072
1073
                                if (status.verbose) {
1074
                                        System.err.println(request);
1075
                                }
1076
1077
                                // The attributes come from ArcIMS in ASCII/cp1252 encoding
1078
                                boolean withUTF = false;
1079
1080
                                // Don't download the file, pass the data directly from the
1081
                                // connection
1082
                                boolean withFile = false;
1083
1084
                                /*
1085
                                 * Get an InputStream from File or directly from the connection
1086
                                 */
1087
                                InputStream is = null;
1088
1089
                                if (withFile) {
1090
                                        File f = ArcImsDownloadUtils.doRequestPost(url, request,
1091
                                                        "getAttributes.xml");
1092
1093
                                        try {
1094
                                                is = new FileInputStream(f);
1095
                                        } catch (FileNotFoundException e) {
1096
                                                logger.error(e.getMessage(), e);
1097
                                        }
1098
                                } else {
1099
                                        is = ArcImsDownloadUtils.getRemoteIS(url, request);
1100
                                }
1101
1102
                                InputStreamReader isr = null;
1103
1104
                                if (withUTF) {
1105
                                        // Deal with UTF-8
1106
                                        try {
1107
                                                isr = new InputStreamReader(is, "UTF-8");
1108
                                        } catch (UnsupportedEncodingException e) {
1109
                                                logger.error(e.getMessage(), e);
1110
                                        }
1111
                                } else {
1112
                                        // No deal with UTF-8
1113
                                        isr = new InputStreamReader(is);
1114
                                }
1115
1116
                                /*
1117
                                 * Finally, we can create a BufferedReader from the
1118
                                 * InputStreamReader
1119
                                 */
1120
                                BufferedReader br = new BufferedReader(isr);
1121
1122
                                /*
1123
                                 * Parse response and return a Rectangle2D
1124
                                 */
1125 32538 vsanjaime
                                String layerId = (String) statusCloned.getLayersIdsSelected().get(0);
1126 32319 vsanjaime
                                logger.debug("Start attributes downloading and parsing ("
1127
                                                + featCount + ") ids retrieved");
1128 32446 vsanjaime
                                features.add(getFeatures(br, statusCloned.getServiceInfo(),
1129 32367 vsanjaime
                                                layerId, statusCloned.getSubfields(), 2)); // Here we
1130
                                // request
1131
                                // envelopes instead
1132
                                // of geometries
1133 32319 vsanjaime
                                logger.debug("End attributes downloading and parsing");
1134
                        }
1135
1136
                        hasMore = true;
1137
                        featCount = 0;
1138
                } catch (MalformedURLException e) {
1139
                        logger.error(e.getMessage(), e);
1140
                        throw new ArcImsException("arcims_server_error");
1141
                } catch (ArcImsException e) {
1142
                        logger.error(e.getMessage(), e);
1143
                        throw new ArcImsException("arcims_server_error");
1144
                } finally {
1145
                        status.setSubfields(subTemp);
1146
                        status.setWhere(whereTemp);
1147
                        status.setEnvelope(rectTemp);
1148
                }
1149
1150
                logger.debug("End attributes retrieving");
1151
1152 32446 vsanjaime
                return features;
1153 32319 vsanjaime
        }
1154
1155
        /*
1156
         * (non-Javadoc)
1157
         *
1158
         * @see
1159
         * org.gvsig.remoteClient.arcims.ArcImsProtocolHandler#getElementInfo(org
1160
         * .gvsig.remoteClient.arcims.ArcImsStatus, int, int, int)
1161
         */
1162
        public String getElementInfo(ArcImsStatus status, int x, int y,
1163
                        int featureCount) throws ArcImsException {
1164
                throw new ClassCastException(
1165
                                "Invalid request, this method is only valid for Image Services");
1166
        }
1167 32446 vsanjaime
}