Statistics
| Revision:

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

History | View | Annotate | Download (30 KB)

1
/* 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
import java.util.Date;
45
import java.util.Hashtable;
46
import java.util.Iterator;
47
import java.util.List;
48
import java.util.StringTokenizer;
49
import java.util.Vector;
50

    
51
import org.gvsig.fmap.dal.feature.impl.DefaultFeature;
52
import org.gvsig.fmap.geom.Geometry;
53
import org.gvsig.fmap.geom.GeometryLocator;
54
import org.gvsig.fmap.geom.GeometryManager;
55
import org.gvsig.fmap.geom.aggregate.impl.MultiPoint2D;
56
import org.gvsig.fmap.geom.exception.CreateGeometryException;
57
import org.gvsig.fmap.geom.primitive.GeneralPathX;
58
import org.gvsig.fmap.geom.primitive.Point;
59
import org.gvsig.remoteclient.arcims.exceptions.ArcImsException;
60
import org.gvsig.remoteclient.arcims.utils.ArcImsDownloadUtils;
61
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
import org.xmlpull.v1.XmlPullParserException;
71

    
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
        public List getMap(ArcImsVectStatus status) throws ArcImsException {
91
                logger.info("Start getMap");
92

    
93
                List array = new ArrayList();
94

    
95
                try {
96
                        /*
97
                         * Build the request
98
                         */
99
                        URL url = new URL(buildCapabilitiesRequest(status));
100

    
101
                        hasMore = true;
102
                        featCount = 1;
103

    
104
                        while (hasMore) {
105
                                /*
106
                                 * Build the proper ArcXML
107
                                 */
108
                                String request = ArcXMLFeatures.getFeatureLayerRequest(status,
109
                                                featCount);
110

    
111
                                if (status.verbose) {
112
                                        System.err.println(request);
113
                                }
114

    
115
                                /*
116
                                 * Request the reader
117
                                 */
118
                                logger.info("Start features downloading");
119

    
120
                                File f = ArcImsDownloadUtils.doRequestPost(url, request,
121
                                                "getFeatures.xml");
122
                                logger.info("End features downloading");
123

    
124
                                /*
125
                                 * Parse response and add geometries to the general Array
126
                                 */
127
                                String layerId = (String) status.getLayerIds().get(0);
128

    
129
                                // Deal with UTF-8
130
                                Reader reader = null;
131
                                FileInputStream fis = new FileInputStream(f);
132
                                InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
133
                                BufferedReader br = new BufferedReader(isr);
134
                                reader = br;
135

    
136
                                logger.debug("Start features with attributes parsing");
137
                                array.add(this.getFeatures(reader, status.getServiceInfo(),
138
                                                layerId, status.getSubfields(), 1));
139
                                logger.debug("End features with attributes parsing");
140
                        }
141

    
142
                        hasMore = true;
143
                        featCount = 1;
144
                } catch (MalformedURLException e) {
145
                        logger.error(e.getMessage(), e);
146
                        throw new ArcImsException("arcims_server_error");
147
                } catch (FileNotFoundException e) {
148
                        logger.error(e.getMessage(), e);
149
                        throw new ArcImsException("arcims_server_error");
150
                } catch (UnsupportedEncodingException e) {
151
                        logger.error(e.getMessage(), e);
152
                }
153

    
154
                logger.debug("End getMap");
155

    
156
                return array;
157
        }
158

    
159
        /**
160
         * Parse the XML data retrieved from ArcIMS GET_FEATURES request to get a
161
         * set of Features if withGeometries is true or an ArrayList of Value[] if
162
         * this boolean is false
163
         * 
164
         * @param Reader
165
         *            Stream to parse
166
         * @param si
167
         *            ServiceInformation with metadata
168
         * @param layerId
169
         *            Layer retrieved
170
         * @param subfields
171
         *            Subfields retrieved
172
         * @param withGeometries
173
         *            Will geometries be parsed?: 0=no 1=yes 2=evelopes
174
         * @return ArrayList of IFeatures or Value[]
175
         * @throws ArcImsException
176
         */
177
        private Hashtable getFeatures(Reader lector, ServiceInformation si,
178
                        String layerId, String[] subfields, int withGeometries)
179
                        throws ArcImsException {
180

    
181
                // TODO
182
                // clear features map
183
                // this.features.clear();
184

    
185
                // fill features map
186
                FieldInformation fi = null;
187
                ServiceInformationLayerFeatures sil = (ServiceInformationLayerFeatures) si
188
                                .getLayerById(layerId);
189

    
190
                /*
191
                 * Prepare a Value array to store every FEATURE tag information
192
                 */
193
                Vector<FieldInformation> fieldsInfo = sil.getFieldsInfo();
194

    
195
                // If flag == true, throw an Exception (no layerId found)
196
                if (fieldsInfo == null) {
197
                        throw new ArcImsException("arcims_no_features");
198
                }
199

    
200
                // We will store names and types in a hashmap
201
                List<FieldInformation> fieldsInfoA = new ArrayList<FieldInformation>();
202

    
203
                /*
204
                 * If subfields[0] is equal to #ALL we add the entire vector into the
205
                 * Hasmap
206
                 */
207
                if (subfields[0].equals("#ALL#")) {
208
                        for (int i = 0; i < fieldsInfo.size(); i++) {
209
                                fi = fieldsInfo.get(i);
210
                                fieldsInfoA.add(fi);
211
                        }
212
                } else {
213
                        for (int i = 0; i < subfields.length; i++) {
214
                                fi = null;
215
                                fi = sil.getFieldInformation(subfields[i]);
216

    
217
                                if (fi != null) {
218
                                        fieldsInfoA.add(fi);
219
                                }
220
                        }
221
                }
222

    
223
                /*
224
                 * Get the separators
225
                 */
226
                String delCoords = si.getSeparators().getCs();
227
                String delTuple = si.getSeparators().getTs();
228
                char delDec = si.getSeparators().getDs();
229

    
230
                /*
231
                 * ArrayList with features
232
                 */
233
                List<DefaultFeature> features = new ArrayList<DefaultFeature>();
234

    
235
                /*
236
                 * Start parsing
237
                 */
238
                int tag;
239
                KXmlParser kxmlParser = new KXmlParser();
240

    
241
                FileReader fr = null;
242
                Geometry geom = null;
243
                // Value[] values = new Value[fieldsInfoA.size()];
244
                // int[] position = new int[fieldsInfoA.size()];
245
                //
246
                // // Initialize position array
247
                // for (int i = 0; i < position.length; i++)
248
                // position[i] = -1;
249
                //
250
                // // long timeFeat = 0;
251
                // // long timeGeom = 0;
252
                // // long timeTemp = 0;
253
                // try {
254
                // kxmlParser.setInput(lector);
255
                // kxmlParser.nextTag();
256
                //
257
                // if (kxmlParser.getEventType() != KXmlParser.END_DOCUMENT) {
258
                // kxmlParser.require(KXmlParser.START_TAG, null,
259
                // ServiceInfoTags.tARCXML);
260
                // tag = kxmlParser.nextTag();
261
                //
262
                // while (tag != KXmlParser.END_DOCUMENT) {
263
                // switch (tag) {
264
                // case KXmlParser.START_TAG:
265
                //
266
                // if (kxmlParser.getName().compareTo(
267
                // GetFeaturesTags.FEATURE) == 0) {
268
                // /*
269
                // * parse FEATURES' tag
270
                // */
271
                //
272
                // // FIRST ENVELOPE TAG (We hope that ENVELOPE will
273
                // // ALLWAYS be returned at first...)
274
                // if (withGeometries == 2) {
275
                // // timeTemp = System.currentTimeMillis();
276
                // geom = parseEnvelopeFromFeatureTag(kxmlParser,
277
                // delDec);
278
                // }
279
                //
280
                // // SECOND FIELDS TAG
281
                // // timeTemp = System.currentTimeMillis();
282
                // values = parseValuesFromFeatureTag(kxmlParser, // the
283
                // // kxml
284
                // // parser
285
                // fieldsInfoA, // Hashmap with names and
286
                // // FieldInformation objects)
287
                // delDec, // the separators
288
                // position // the relative positions of
289
                // // returned values
290
                // );
291
                //
292
                // // timeFeat += System.currentTimeMillis() -
293
                // // timeTemp;
294
                //
295
                // // If geometries are neede we add to the ArrayList
296
                // // the Ifeature
297
                // if (withGeometries == 1) {
298
                // // THIRD GEOMETRIES
299
                // // timeTemp = System.currentTimeMillis();
300
                // geom = parseGeomFromFeatureTag(kxmlParser, // the
301
                // // kxml
302
                // // parser
303
                // delTuple, delCoords, delDec // the
304
                // // separators
305
                // );
306
                //
307
                // // timeGeom += System.currentTimeMillis() -
308
                // // timeTemp;
309
                // }
310
                //
311
                // // If some geometry is created, we add a IFeature
312
                // // into features ArrayList
313
                // if (withGeometries > 0) {
314
                // features.add(new DefaultFeature(geom, values));
315
                // }
316
                // // Else we only need the Value[] array
317
                // else {
318
                // features.add(values);
319
                // }
320
                // } else if (kxmlParser.getName().compareTo(
321
                // GetFeaturesTags.FEATURECOUNT) == 0) {
322
                // String value = new String();
323
                //
324
                // // Get the feature count
325
                // value = kxmlParser.getAttributeValue("",
326
                // GetFeaturesTags.COUNT);
327
                //
328
                // Integer intFeatCount = new Integer(value);
329
                // featCount += intFeatCount.intValue();
330
                //
331
                // // Get the hasmore boolean
332
                // value = kxmlParser.getAttributeValue("",
333
                // GetFeaturesTags.HASMORE);
334
                //
335
                // Boolean boHasMore = new Boolean(value);
336
                // hasMore = boHasMore.booleanValue();
337
                // } else if (kxmlParser.getName().compareTo(
338
                // ServiceInfoTags.tERROR) == 0) {
339
                // logger.error("Error parsing GET_FEATURES:\r\n"
340
                // + kxmlParser.nextText());
341
                // throw new ArcImsException("arcims_server_error");
342
                // }
343
                //
344
                // break;
345
                //
346
                // case KXmlParser.END_TAG:
347
                // break;
348
                //
349
                // case KXmlParser.TEXT:
350
                // break;
351
                // }
352
                //
353
                // tag = kxmlParser.next();
354
                // }
355
                //
356
                // kxmlParser.require(KXmlParser.END_DOCUMENT, null, null);
357
                // }
358
                // } catch (ParseException pe) {
359
                // logger.error(pe.getMessage(), pe);
360
                // throw new ArcImsException("arcims_no_features");
361
                // } catch (XmlPullParserException parser_ex) {
362
                // logger.error(parser_ex.getMessage(), parser_ex);
363
                // throw new ArcImsException("arcims_no_features");
364
                // } catch (IOException ioe) {
365
                // logger.error(ioe.getMessage(), ioe);
366
                // throw new ArcImsException("arcims_no_features");
367
                // }
368
                //
369
                // // logger.debug("Time for parsing features " + timeFeat + " msecs");
370
                // // logger.debug("Time for parsing geometries " + timeGeom +
371
                // " msecs");
372
                // return features;
373
                return null;
374
        }
375

    
376
        /**
377
         * Returns an IGeometry with a line between corners of an ENVELOPE
378
         * 
379
         * @param parser
380
         * @param delDec
381
         * @return
382
         * @throws XmlPullParserException
383
         * @throws IOException
384
         */
385
        private Geometry parseEnvelopeFromFeatureTag(KXmlParser parser, char delDec)
386
                        throws XmlPullParserException, IOException {
387
                int currentTag;
388
                boolean end = false;
389
                int f = 0;
390
                String att;
391
                String val;
392
                int type;
393

    
394
                BoundaryBox bb = null;
395

    
396
                // parser.require(KXmlParser.START_TAG,null,GetFeaturesTags.FIELDS);
397
                currentTag = parser.next();
398

    
399
                while (!end) {
400
                        switch (currentTag) {
401
                        case KXmlParser.START_TAG:
402

    
403
                                if (parser.getName().equals(ServiceInfoTags.tENVELOPE)) {
404
                                        bb = super.parseEnvelope(parser, delDec);
405
                                        end = true;
406
                                }
407

    
408
                                break;
409

    
410
                        case KXmlParser.END_TAG:
411

    
412
                                if (parser.getName().equals(GetFeaturesTags.FIELDS)) {
413
                                        end = true;
414
                                }
415

    
416
                                break;
417

    
418
                        case KXmlParser.TEXT:
419
                                break;
420
                        }
421

    
422
                        if (!end) {
423
                                currentTag = parser.next();
424
                        }
425
                }
426

    
427
                // If BoundaryBox object has been created, we can convert it into a
428
                // IGeometry (polyline).
429
                if (bb != null) {
430
                        GeneralPathX polyline = new GeneralPathX(GeneralPathX.WIND_EVEN_ODD);
431

    
432
                        polyline.moveTo(bb.getXmin(), bb.getYmin());
433
                        polyline.lineTo(bb.getXmax(), bb.getYmax());
434

    
435
                        GeometryManager geomManager = GeometryLocator.getGeometryManager();
436
                        Geometry curve = null;
437
                        try {
438
                                curve = geomManager.createCurve(polyline,
439
                                                Geometry.SUBTYPES.GEOM2D);
440
                        } catch (CreateGeometryException e) {
441
                                logger.error("Error creating curve", e);
442
                                return null;
443
                        }
444
                        return curve;
445
                } else {
446
                        return null;
447
                }
448

    
449
        }
450

    
451
        /**
452
         * @param kxmlParser
453
         * @param fieldsInfoH
454
         * @param delDec
455
         * @param position
456
         * @return
457
         * @throws IOException
458
         * @throws XmlPullParserException
459
         * @throws IOException
460
         * @throws XmlPullParserException
461
         * @throws ArcImsException
462
         * @throws ArcImsException
463
         * @throws ParseException
464
         */
465
        private Object[] parseValuesFromFeatureTag(KXmlParser parser,
466
                        List fieldsInfoA, char delDec, int[] position)
467
                        throws XmlPullParserException, IOException, ArcImsException {
468

    
469
                int currentTag;
470
                boolean end = false;
471
                int f = 0;
472
                String att;
473
                String text;
474
                int type;
475

    
476
                Object[] values = new Object[fieldsInfoA.size()];
477

    
478
                currentTag = parser.next();
479

    
480
                while (!end) {
481
                        switch (currentTag) {
482
                        case KXmlParser.START_TAG:
483

    
484
                                if (parser.getName().equals(GetFeaturesTags.FIELD)) {
485
                                        att = parser.getAttributeValue("", GetFeaturesTags.NAME);
486
                                        text = parser.getAttributeValue("", GetFeaturesTags.VALUE);
487

    
488
                                        /*
489
                                         * As NAME is known, we need to get the position of that
490
                                         * attribute into the ArrayList of fieldInformation objects
491
                                         */
492
                                        if (position[f] == -1) {
493
                                                position[f] = getPosition(fieldsInfoA.iterator(), att);
494
                                        }
495

    
496
                                        if (position[f] == -1) {
497
                                                logger.error("Attribute not found at Metadata");
498
                                                throw new ArcImsException(
499
                                                                "Attribute not found at Metadata");
500
                                        }
501

    
502
                                        // This way we can create a NullValue
503
                                        if (text.equals("")) {
504
                                                text = null;
505
                                        }
506

    
507
                                        /*
508
                                         * At this point we know wat FieldInfo of the ArrayList we
509
                                         * have to retrieve
510
                                         */
511
                                        type = ((FieldInformation) fieldsInfoA.get(position[f]))
512
                                                        .getType();
513

    
514
                                        // Add the Value into the correct position
515
                                        if (text == null) {
516
                                                values[position[f]] = null;
517
                                        } else {
518
                                                switch (type) {
519
                                                case FieldInformation.BOOLEAN:
520
                                                        values[position[f]] = new Boolean(text);
521
                                                        f++;
522
                                                        break;
523
                                                case FieldInformation.SHAPE:
524
                                                case FieldInformation.STRING:
525
                                                        values[position[f]] = new String(text);
526
                                                        f++;
527
                                                        break;
528
                                                case FieldInformation.DATE:
529
                                                        values[position[f]] = new Date(Long.parseLong(text));
530
                                                        f++;
531
                                                        break;
532
                                                case FieldInformation.FLOAT:
533
                                                        String textfloat = text.replace(delDec, '.');
534
                                                        values[position[f]] = new Float(textfloat);
535
                                                        f++;
536
                                                        break;
537
                                                case FieldInformation.DOUBLE:
538
                                                        String textdouble = text.replace(delDec, '.');
539
                                                        values[position[f]] = new Double(textdouble);
540
                                                        f++;
541
                                                        break;
542
                                                case FieldInformation.SMALLINT:
543
                                                        values[position[f]] = new Short(text);
544
                                                        f++;
545
                                                        break;
546
                                                case FieldInformation.BIGINT:
547
                                                        values[position[f]] = new Long(text);
548
                                                        f++;
549
                                                        break;
550
                                                case FieldInformation.ID:
551
                                                case FieldInformation.INTEGER:
552
                                                        values[position[f]] = new Integer(text);
553
                                                        f++;
554
                                                        break;
555
                                                default:
556
                                                        values[position[f]] = new String(text);
557
                                                        f++;
558
                                                }
559
                                        }
560
                                }
561

    
562
                                break;
563

    
564
                        case KXmlParser.END_TAG:
565

    
566
                                if (parser.getName().equals(GetFeaturesTags.FIELDS)) {
567
                                        end = true;
568
                                }
569

    
570
                                break;
571

    
572
                        case KXmlParser.TEXT:
573
                                break;
574
                        }
575

    
576
                        if (!end) {
577
                                currentTag = parser.next();
578
                        }
579
                }
580

    
581
                return values;
582

    
583
        }
584

    
585
        /**
586
         * Method to get the position of an attribute into the subfields array
587
         * 
588
         * @param fieldsInfoA
589
         * @param att
590
         * @return
591
         */
592
        private int getPosition(Iterator it, String att) {
593
                int res = 0;
594
                FieldInformation fi;
595

    
596
                while (it.hasNext()) {
597
                        fi = (FieldInformation) it.next();
598

    
599
                        if (fi.getName().equals(att)) {
600
                                return res;
601
                        }
602

    
603
                        res++;
604
                }
605

    
606
                // If no integer has returned at this point we return a -1
607
                return -1;
608
        }
609

    
610
        /**
611
         * Parses the Feature Tag to get a IFeature
612
         * 
613
         * @param KxmlParser
614
         *            with the FEATURE tag
615
         * @param Value
616
         *            array with the correct subtypes to store FIELDS data
617
         * @param String
618
         *            array with the correct fields names to retrieve
619
         * @param String
620
         *            with the tuple separator
621
         * @param String
622
         *            with the coordinates separator
623
         * @param Char
624
         *            with the decimal separator
625
         * @return @see com.hardcode.gdbms.engine.values.Value.IFeature
626
         * @throws IOException
627
         * @throws XmlPullParserException
628
         * @throws IOException
629
         * @throws XmlPullParserException
630
         * @throws CreateGeometryException
631
         * @throws ArcImsException
632
         * @throws CreateGeometryException
633
         * @throws ArcImsException
634
         */
635
        private Geometry parseGeomFromFeatureTag(KXmlParser parser,
636
                        String delTuple, String delCoords, char delDec)
637
                        throws XmlPullParserException, IOException,
638
                        CreateGeometryException, ArcImsException {
639

    
640
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
641
                int currentTag;
642
                boolean end = false;
643
                Geometry geom = null;
644
                currentTag = parser.next();
645

    
646
                while (!end) {
647
                        String featType = parser.getName();
648

    
649
                        switch (currentTag) {
650
                        case KXmlParser.START_TAG:
651
                                // //////////////////////////
652
                                // geometry type MULTIPOINT
653
                                // //////////////////////////
654
                                if (featType.equals(GetFeaturesTags.MULTIPOINT)) {
655
                                        // Go to COORDS tag
656
                                        parser.nextTag();
657

    
658
                                        if (parser.getName().equals(GetFeaturesTags.COORDS)) {
659
                                                // Create a tokenizer with the tuples
660
                                                String strPoints = parser.nextText();
661

    
662
                                                // Get the points from COORDS string
663
                                                List<Point> points = parseCoords(strPoints, delTuple,
664
                                                                delCoords, delDec);
665

    
666
                                                geom = geomManager.create(Geometry.TYPES.MULTIPOINT,
667
                                                                Geometry.SUBTYPES.GEOM2D);
668
                                                MultiPoint2D mpoint = (MultiPoint2D) geom;
669
                                                for (Point point : points) {
670
                                                        mpoint.addPoint(point);
671
                                                }
672
                                        } else {
673
                                                logger.error("Error parsing MULTIPOINT tag");
674
                                                throw new ArcImsException("arcims_features_error");
675
                                        }
676
                                }
677
                                // ////////////////////////////////////////////
678
                                // POLYLINE or POLYGON
679
                                // ////////////////////////////////////////////
680
                                else if (featType.equals(GetFeaturesTags.POLYLINE)
681
                                                || featType.equals(GetFeaturesTags.POLYGON)) {
682
                                        // Parse while parser doesn't found </FEATURES> tag
683
                                        // The GeneralPath to store the different paths
684
                                        GeneralPathX polyline = new GeneralPathX(
685
                                                        GeneralPathX.WIND_EVEN_ODD);
686
                                        boolean endpol = false;
687

    
688
                                        while (!endpol) {
689
                                                switch (currentTag) {
690
                                                case KXmlParser.START_TAG:
691

    
692
                                                        if (parser.getName().equals(GetFeaturesTags.COORDS)) {
693
                                                                // Create a tokenizer with the tuples
694
                                                                String strPoints = parser.nextText();
695

    
696
                                                                // Get the points (Point2D) from COORDS string
697
                                                                List<Point> points = parseCoords(strPoints,
698
                                                                                delTuple, delCoords, delDec);
699

    
700
                                                                Iterator it = points.iterator();
701
                                                                Point point;
702

    
703
                                                                // First we MOVE to the first point of the path
704
                                                                point = (Point) it.next();
705
                                                                polyline.moveTo(point.getX(), point.getY());
706

    
707
                                                                // And now we can LINE to the rest of the points
708
                                                                // of the path
709
                                                                while (it.hasNext()) {
710
                                                                        point = (Point) it.next();
711
                                                                        polyline.lineTo(point.getX(), point.getY());
712
                                                                }
713
                                                        }
714

    
715
                                                        break;
716

    
717
                                                case KXmlParser.END_TAG:
718

    
719
                                                        if (parser.getName().equals(featType)) {
720
                                                                endpol = true;
721
                                                        }
722

    
723
                                                        break;
724

    
725
                                                case KXmlParser.TEXT:
726
                                                        break;
727
                                                }
728

    
729
                                                if (!endpol) {
730
                                                        currentTag = parser.next();
731
                                                }
732
                                        }
733

    
734
                                        if (featType.equals(GetFeaturesTags.POLYLINE)) {
735
                                                geom = geomManager.createMultiCurve(polyline,
736
                                                                Geometry.SUBTYPES.GEOM2D);
737
                                        } else if (featType.equals(GetFeaturesTags.POLYGON)) {
738
                                                geom = geomManager.createMultiSurface(polyline,
739
                                                                Geometry.SUBTYPES.GEOM2D);
740
                                        }
741
                                }
742

    
743
                                break;
744

    
745
                        case KXmlParser.END_TAG:
746

    
747
                                if (parser.getName().compareTo(GetFeaturesTags.FEATURE) == 0) {
748
                                        end = true;
749
                                }
750

    
751
                                break;
752

    
753
                        case KXmlParser.TEXT:
754
                                break;
755
                        }
756

    
757
                        if (!end) {
758
                                currentTag = parser.next();
759
                        }
760
                }
761

    
762
                return geom;
763
        }
764

    
765
        /**
766
         * Private method that parses a COORDS tag to return an ArrayList of
767
         * Point2D.Double objects
768
         * 
769
         * @param strCoords
770
         * @param delTuple
771
         * @param delCoords
772
         * @param delDec
773
         * @return
774
         * @throws CreateGeometryException
775
         */
776
        private List<Point> parseCoords(String strCoords, String delTuple,
777
                        String delCoords, char delDec) throws CreateGeometryException {
778

    
779
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
780
                List<Point> points = new ArrayList<Point>();
781
                String tupla = new String();
782
                String[] tuplaPart;
783
                Double x;
784
                Double y;
785

    
786
                /*
787
                 * Replaces Decimal Separator to convert coords to suitable doubles.
788
                 * 
789
                 * Maybe it will have a better performance if we insert this replace
790
                 * into the while
791
                 */
792
                if (delDec != '.') {
793
                        strCoords = strCoords.replace(delDec, '.');
794
                }
795

    
796
                // Creates a tokenizer to run over the string
797
                StringTokenizer tuplas = new StringTokenizer(strCoords, delTuple, false);
798

    
799
                // Get ArrayLists collections with X's and Y's
800
                while (tuplas.hasMoreTokens()) {
801
                        // tupla = tuplas.nextToken().replace(delDec,'.');
802
                        tupla = tuplas.nextToken();
803
                        tuplaPart = tupla.split(delCoords);
804
                        x = new Double(tuplaPart[0]);
805
                        y = new Double(tuplaPart[1]);
806

    
807
                        Point pto = geomManager.createPoint(x.doubleValue(), y
808
                                        .doubleValue(), Geometry.SUBTYPES.GEOM2D);
809
                        points.add(pto);
810
                }
811

    
812
                // Return an array of Point objects
813
                return points;
814
        }
815

    
816
        /**
817
         * @param status
818
         * @return
819
         * @throws ArcImsException
820
         */
821
        public Rectangle2D getLayerExtent(ArcImsVectStatus status)
822
                        throws ArcImsException {
823
                Rectangle2D envelope = null;
824
                String layerId = (String) status.getLayerIds().get(0);
825

    
826
                // logger.info("Getting Vectorial Layer Extent (" + status.getl)
827
                ServiceInformation si = status.getServiceInfo();
828
                String ini_srs = ServiceInfoTags.vINI_SRS;
829

    
830
                String srsView = status.getSrs().substring(ini_srs.length()).trim();
831
                String srsServ = si.getFeaturecoordsys();
832
                boolean srsAssumed = si.isSrsAssumed();
833

    
834
                if (srsAssumed || (srsView.equals(srsServ))) {
835
                        BoundaryBox bb = si.getLayerById(layerId).getEnvelope();
836

    
837
                        /*
838
                         * At the end, we convert the BoundaryBox to a Rectangle2D
839
                         */
840
                        envelope = new Rectangle2D.Double();
841

    
842
                        envelope.setFrameFromDiagonal(bb.getXmin(), bb.getYmin(), bb
843
                                        .getXmax(), bb.getYmax());
844

    
845
                        return envelope;
846
                }
847

    
848
                /*
849
                 * If SRS of View and Service are different, we do a custom request to
850
                 * retrieve the global envelope of the layer
851
                 */
852
                try {
853
                        /*
854
                         * Build the request
855
                         */
856
                        URL url;
857
                        url = new URL(buildCapabilitiesRequest(status));
858

    
859
                        /*
860
                         * Build the proper ArcXML
861
                         */
862
                        String request = ArcXMLFeatures.getLayerExtentRequest(status);
863

    
864
                        if (status.verbose) {
865
                                System.err.println(request);
866
                        }
867

    
868
                        /*
869
                         * Request the envelope
870
                         */
871
                        File response;
872
                        response = ArcImsDownloadUtils.doRequestPost(url, request,
873
                                        "getLayerExtent.xml");
874

    
875
                        /*
876
                         * Parse response and return a Rectangle2D
877
                         */
878
                        char ds = si.getSeparators().getDs();
879
                        envelope = parseEnvelopeTag(new FileReader(response), ds);
880
                } catch (MalformedURLException e) {
881
                        logger.error(e.getMessage(), e);
882
                        throw new ArcImsException("arcims_server_error");
883
                } catch (FileNotFoundException e) {
884
                        logger.error(e.getMessage(), e);
885
                        throw new ArcImsException("arcims_server_error");
886
                }
887

    
888
                return envelope;
889
        }
890

    
891
        /**
892
         * Retrieves an ArrayList of Value arrays. The query can be filtered by a
893
         * WHERE clause or an envelope. Only subfields passed will be retrieved
894
         * 
895
         * @param status
896
         * @param subfields
897
         * @param where
898
         * @param envelope
899
         * @return
900
         * @throws ArcImsException
901
         */
902
        public List getAttributes(ArcImsVectStatus status, String[] subfields,
903
                        String where, Rectangle2D envelope) throws ArcImsException {
904

    
905
                logger.info("Start getAttributes");
906

    
907
                List valuesArray = new ArrayList();
908

    
909
                // Clone the status and set temporal subfields and where clause
910
                ArcImsVectStatus statusCloned = status;
911

    
912
                String[] subTemp = status.getSubfields();
913
                String whereTemp = status.getWhere();
914
                Rectangle2D rectTemp = status.getEnvelopeRect();
915

    
916
                statusCloned.setSubfields(subfields);
917
                statusCloned.setWhere(where);
918
                statusCloned.setEnvelope(envelope);
919

    
920
                try {
921
                        /*
922
                         * Build the request
923
                         */
924
                        URL url;
925
                        url = new URL(buildCapabilitiesRequest(statusCloned));
926

    
927
                        hasMore = true;
928
                        featCount = 0;
929

    
930
                        while (hasMore) {
931
                                /*
932
                                 * Build the proper ArcXML
933
                                 */
934
                                String request = ArcXMLFeatures.getAttributesRequest(
935
                                                statusCloned, featCount);
936

    
937
                                if (status.verbose) {
938
                                        System.err.println(request);
939
                                }
940

    
941
                                // The attributes come from ArcIMS in ASCII/cp1252 encoding
942
                                boolean withUTF = false;
943

    
944
                                // Don't download the file, pass the data directly from the
945
                                // connection
946
                                boolean withFile = false;
947

    
948
                                /*
949
                                 * Get an InputStream from File or directly from the connection
950
                                 */
951
                                InputStream is = null;
952

    
953
                                if (withFile) {
954
                                        File f = ArcImsDownloadUtils.doRequestPost(url, request,
955
                                                        "getAttributes.xml");
956

    
957
                                        try {
958
                                                is = new FileInputStream(f);
959
                                        } catch (FileNotFoundException e) {
960
                                                logger.error(e.getMessage(), e);
961
                                        }
962
                                } else {
963
                                        is = ArcImsDownloadUtils.getRemoteIS(url, request);
964
                                }
965

    
966
                                InputStreamReader isr = null;
967

    
968
                                if (withUTF) {
969
                                        // Deal with UTF-8
970
                                        try {
971
                                                isr = new InputStreamReader(is, "UTF-8");
972
                                        } catch (UnsupportedEncodingException e) {
973
                                                logger.error(e.getMessage(), e);
974
                                        }
975
                                } else {
976
                                        // No deal with UTF-8
977
                                        isr = new InputStreamReader(is);
978
                                }
979

    
980
                                /*
981
                                 * Finally, we can create a BufferedReader from the
982
                                 * InputStreamReader
983
                                 */
984
                                BufferedReader br = new BufferedReader(isr);
985

    
986
                                /*
987
                                 * Parse response and return a Rectangle2D
988
                                 */
989
                                String layerId = (String) statusCloned.getLayerIds().get(0);
990
                                logger.debug("Start attributes downloading and parsing ("
991
                                                + featCount + ") ids retrieved");
992
                                valuesArray.add(getFeatures(br, statusCloned.getServiceInfo(),
993
                                                layerId, statusCloned.getSubfields(), 0));
994
                                logger.debug("End attributes downloading and parsing");
995
                        }
996

    
997
                        hasMore = true;
998
                        featCount = 0;
999
                } catch (MalformedURLException e) {
1000
                        logger.error(e.getMessage(), e);
1001
                        throw new ArcImsException("arcims_server_error");
1002
                } catch (ArcImsException e) {
1003
                        logger.error(e.getMessage(), e);
1004
                        throw new ArcImsException("arcims_server_error");
1005
                } finally {
1006
                        status.setSubfields(subTemp);
1007
                        status.setWhere(whereTemp);
1008
                        status.setEnvelope(rectTemp);
1009
                }
1010

    
1011
                logger.debug("End attributes retrieving");
1012

    
1013
                return valuesArray;
1014
        }
1015

    
1016
        /**
1017
         * Retrieves an ArrayList of I by some IDs. The geometry returned is the
1018
         * envelope of the feature requested. The query can be filtered by a WHERE
1019
         * clause or an envelope. Only subfields passed will be retrieved
1020
         * 
1021
         * @param status
1022
         * @param subfields
1023
         * @param where
1024
         * @param envelope
1025
         * @return
1026
         * @throws ArcImsException
1027
         */
1028
        public ArrayList getAttributesWithEnvelope(ArcImsVectStatus status,
1029
                        String[] subfields, String where, Rectangle2D envelope)
1030
                        throws ArcImsException {
1031

    
1032
                logger.info("Start getAttributesWihtEnvelope");
1033

    
1034
                ArrayList valuesArray = new ArrayList();
1035

    
1036
                // Clone the status and set temporal subfields and where clause
1037
                ArcImsVectStatus statusCloned = status;
1038

    
1039
                String[] subTemp = status.getSubfields();
1040
                String whereTemp = status.getWhere();
1041
                Rectangle2D rectTemp = status.getEnvelopeRect();
1042

    
1043
                statusCloned.setSubfields(subfields);
1044
                statusCloned.setWhere(where);
1045
                statusCloned.setEnvelope(envelope);
1046

    
1047
                try {
1048
                        /*
1049
                         * Build the request
1050
                         */
1051
                        URL url;
1052
                        url = new URL(buildCapabilitiesRequest(statusCloned));
1053

    
1054
                        hasMore = true;
1055
                        featCount = 0;
1056

    
1057
                        while (hasMore) {
1058
                                /*
1059
                                 * Build the proper ArcXML
1060
                                 */
1061
                                String request = ArcXMLFeatures.getAttributesRequest(
1062
                                                statusCloned, featCount);
1063

    
1064
                                if (status.verbose) {
1065
                                        System.err.println(request);
1066
                                }
1067

    
1068
                                // The attributes come from ArcIMS in ASCII/cp1252 encoding
1069
                                boolean withUTF = false;
1070

    
1071
                                // Don't download the file, pass the data directly from the
1072
                                // connection
1073
                                boolean withFile = false;
1074

    
1075
                                /*
1076
                                 * Get an InputStream from File or directly from the connection
1077
                                 */
1078
                                InputStream is = null;
1079

    
1080
                                if (withFile) {
1081
                                        File f = ArcImsDownloadUtils.doRequestPost(url, request,
1082
                                                        "getAttributes.xml");
1083

    
1084
                                        try {
1085
                                                is = new FileInputStream(f);
1086
                                        } catch (FileNotFoundException e) {
1087
                                                logger.error(e.getMessage(), e);
1088
                                        }
1089
                                } else {
1090
                                        is = ArcImsDownloadUtils.getRemoteIS(url, request);
1091
                                }
1092

    
1093
                                InputStreamReader isr = null;
1094

    
1095
                                if (withUTF) {
1096
                                        // Deal with UTF-8
1097
                                        try {
1098
                                                isr = new InputStreamReader(is, "UTF-8");
1099
                                        } catch (UnsupportedEncodingException e) {
1100
                                                logger.error(e.getMessage(), e);
1101
                                        }
1102
                                } else {
1103
                                        // No deal with UTF-8
1104
                                        isr = new InputStreamReader(is);
1105
                                }
1106

    
1107
                                /*
1108
                                 * Finally, we can create a BufferedReader from the
1109
                                 * InputStreamReader
1110
                                 */
1111
                                BufferedReader br = new BufferedReader(isr);
1112

    
1113
                                /*
1114
                                 * Parse response and return a Rectangle2D
1115
                                 */
1116
                                String layerId = (String) statusCloned.getLayerIds().get(0);
1117
                                logger.debug("Start attributes downloading and parsing ("
1118
                                                + featCount + ") ids retrieved");
1119
                                valuesArray.add(getFeatures(br, statusCloned.getServiceInfo(),
1120
                                                layerId, statusCloned.getSubfields(), 2)); // Here we
1121
                                // request
1122
                                // envelopes instead
1123
                                // of geometries
1124
                                logger.debug("End attributes downloading and parsing");
1125
                        }
1126

    
1127
                        hasMore = true;
1128
                        featCount = 0;
1129
                } catch (MalformedURLException e) {
1130
                        logger.error(e.getMessage(), e);
1131
                        throw new ArcImsException("arcims_server_error");
1132
                } catch (ArcImsException e) {
1133
                        logger.error(e.getMessage(), e);
1134
                        throw new ArcImsException("arcims_server_error");
1135
                } finally {
1136
                        status.setSubfields(subTemp);
1137
                        status.setWhere(whereTemp);
1138
                        status.setEnvelope(rectTemp);
1139
                }
1140

    
1141
                logger.debug("End attributes retrieving");
1142

    
1143
                return valuesArray;
1144
        }
1145

    
1146
        /*
1147
         * (non-Javadoc)
1148
         * 
1149
         * @see
1150
         * org.gvsig.remoteClient.arcims.ArcImsProtocolHandler#getElementInfo(org
1151
         * .gvsig.remoteClient.arcims.ArcImsStatus, int, int, int)
1152
         */
1153
        public String getElementInfo(ArcImsStatus status, int x, int y,
1154
                        int featureCount) throws ArcImsException {
1155
                throw new ClassCastException(
1156
                                "Invalid request, this method is only valid for Image Services");
1157
        }
1158
}