Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / extensions / extWMS / src / org / gvsig / wmc / WebMapContext.java @ 31515

History | View | Annotate | Download (37.3 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2005 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41

    
42
/* CVS MESSAGES:
43
*
44
* $Id: WebMapContext.java 31515 2009-11-05 15:53:13Z cordinyana $
45
* $Log$
46
* Revision 1.9  2007-03-06 17:06:43  caballero
47
* Exceptions
48
*
49
* Revision 1.8  2007/01/08 07:57:34  jaume
50
* *** empty log message ***
51
*
52
* Revision 1.7  2006/09/26 14:41:48  jaume
53
* *** empty log message ***
54
*
55
* Revision 1.6  2006/09/25 10:23:26  caballero
56
* Projection
57
*
58
* Revision 1.5  2006/09/15 10:44:24  caballero
59
* extensibilidad de documentos
60
*
61
* Revision 1.4  2006/07/21 10:31:05  jaume
62
* *** empty log message ***
63
*
64
* Revision 1.3  2006/05/24 16:36:28  jaume
65
* *** empty log message ***
66
*
67
* Revision 1.2  2006/05/12 07:47:39  jaume
68
* removed unnecessary imports
69
*
70
* Revision 1.1  2006/05/03 07:51:21  jaume
71
* *** empty log message ***
72
*
73
* Revision 1.10  2006/05/02 15:57:44  jaume
74
* Few better javadoc
75
*
76
* Revision 1.9  2006/04/25 11:40:56  jaume
77
* *** empty log message ***
78
*
79
* Revision 1.8  2006/04/25 10:01:56  jaume
80
* fixed extend bug when importing
81
*
82
* Revision 1.7  2006/04/21 12:46:53  jaume
83
* *** empty log message ***
84
*
85
* Revision 1.6  2006/04/21 11:53:50  jaume
86
* *** empty log message ***
87
*
88
* Revision 1.5  2006/04/21 11:02:25  jaume
89
* few translations
90
*
91
* Revision 1.4  2006/04/21 10:27:32  jaume
92
* exporting now supported
93
*
94
* Revision 1.3  2006/04/20 17:11:54  jaume
95
* Attempting to export
96
*
97
* Revision 1.2  2006/04/19 16:34:29  jaume
98
* *** empty log message ***
99
*
100
* Revision 1.1  2006/04/19 07:57:29  jaume
101
* *** empty log message ***
102
*
103
* Revision 1.1  2006/04/12 17:10:53  jaume
104
* *** empty log message ***
105
*
106
*
107
*/
108
package org.gvsig.wmc;
109

    
110
import java.awt.Dimension;
111
import java.awt.geom.Rectangle2D;
112
import java.io.BufferedReader;
113
import java.io.File;
114
import java.io.FileInputStream;
115
import java.io.FileNotFoundException;
116
import java.io.FileReader;
117
import java.io.IOException;
118
import java.net.URL;
119
import java.util.ArrayList;
120
import java.util.HashMap;
121
import java.util.HashSet;
122
import java.util.Hashtable;
123
import java.util.Vector;
124

    
125
import org.cresques.cts.ICoordTrans;
126
import org.cresques.cts.IProjection;
127
import org.gvsig.andami.PluginServices;
128
import org.gvsig.andami.messages.NotificationManager;
129
import org.gvsig.app.ApplicationLocator;
130
import org.gvsig.app.project.DefaultProject;
131
import org.gvsig.app.project.documents.view.DefaultViewDocument;
132
import org.gvsig.fmap.crs.CRSFactory;
133
import org.gvsig.fmap.mapcontext.exceptions.UnsupportedVersionLayerException;
134
import org.gvsig.fmap.mapcontext.layers.FLayer;
135
import org.gvsig.fmap.mapcontext.layers.FLayers;
136
import org.gvsig.wms.fmap.exceptions.ImportMapContextException;
137
import org.gvsig.wms.fmap.layers.FLyrWMS;
138
import org.gvsig.wms.fmap.layers.WMSLayerNode;
139
import org.gvsig.wms.fmap.layers.WMSLayerNode.FMapWMSStyle;
140
import org.kxml2.io.KXmlParser;
141
import org.xmlpull.v1.XmlPullParserException;
142

    
143

    
144
/**
145
 * Class that loads and produces WebMapContext files and holds its attributes.
146
 *
147
 * You can create a blank WebMapContext instance using the default constructor
148
 * or an already initialized instance by specifying a source file. In the last
149
 * case the file will be readed and the values loaded an holded by the instance.
150
 *
151
 * You can get the equivalent WebMapContext XML document by calling the method
152
 * getXML() supplying the ProjectView that you want to export and depending on
153
 * the value of the fileVersion field (currently you can use "1.1.0" (default),
154
 * "1.0.0" or "0.4.1" to specify the destination document version.
155
 *
156
 * @author jaume dominguez faus - jaume.dominguez@iver.es
157
 */
158
public class WebMapContext {
159
        public final static String FILE_EXTENSION = ".cml";
160

    
161
        static final ArrayList supportedVersions = new ArrayList();
162
        static public final ArrayList exportVersions    = new ArrayList();
163
        static private HashSet supportedLayers = new HashSet();
164
        private File mapContextFile;
165
        private String encoding = "UTF-8";
166
        private String WMC_START_TAG;
167

    
168
        // MapContext stuff
169
        public String fileVersion = null;
170
        public Dimension windowSize = null;
171
        public String srs = null;
172
        public Rectangle2D bBox = null;
173
        public String title = null;
174
        public String id = null;
175
        public String xmlns = null;
176
        public String xmlns_xlink = null;
177
        public String xmlns_xsi = null;;
178
        public String xsi_schemaLocation = null;
179
        public String _abstract = null;
180
        public ArrayList keywordList = null;
181
        public Dimension logoURLSize = null;
182
        public String logoURLFormat = null;
183
        public String logoURL = null;
184
        public String descriptionURLFormat = null;
185
        public String descriptionURL = null;
186
        public boolean contactInfo = false;
187
        public String contactPerson = null;
188
        public String contactOrganization = null;
189
        public String contactPosition = null;
190
        public String address = null;
191
        public String city = null;
192
        public String stateOrProvince = null;
193
        public String postCode = null;
194
        public String country = null;
195
        public String telephone = null;
196
        public String fax = null;
197
        public String email = null;
198

    
199
        private StringBuffer errorMessages;
200

    
201
        /**
202
         * list of FLyrWMS.
203
         */
204
        ArrayList<FLyrWMS> layerList = null;
205

    
206
        /**
207
         * key: server URL (URL)
208
         * value: server title (String)
209
         */
210
        Hashtable serverTitles = null;
211

    
212
        /**
213
         * key: layer FLyrWMS
214
         * value: layer abstract (String)
215
         */
216
        Hashtable layerAbstracts = null;
217

    
218
        /**
219
         * key: layer FLyrWMS
220
         * value: layer formats (String[])
221
         */
222
        Hashtable layerFormats = null;
223

    
224
        /**
225
         * key: layer FLyrWMS
226
         * value: styles (FMapWMSStyle[])
227
         */
228
        Hashtable layerStyles = null;
229

    
230

    
231
        static {
232
                supportedVersions.add("1.1.0");
233
                supportedVersions.add("1.0.0");
234
                supportedVersions.add("0.1.4");
235
        }
236

    
237
        static {
238
                exportVersions.add("1.1.0");
239
                exportVersions.add("1.0.0");
240
                exportVersions.add("0.1.4");
241
        }
242

    
243
        static {
244
                supportedLayers.add(FLyrWMS.class);
245
        }
246

    
247

    
248
        /**
249
         * Initializes the WebMapContext properties from the values in the WebMapContext (.cml)
250
         * file passed in the argument.
251
         * @param file
252
         * @throws UnsupportedVersionLayerException
253
         * @throws ImportMapContextException
254
         */
255
        public void readFile(File file) throws UnsupportedVersionLayerException, ImportMapContextException {
256
                this.mapContextFile = file;
257
                errorMessages = new StringBuffer();
258
                if (getVersion()!=null) {
259
                        if (supportedVersions.contains(getVersion())) {
260
                                WMC_START_TAG = WebMapContextTags.VIEW_CONTEXT;
261
                                if (getVersion().equals("0.1.4")) {
262
                                        WMC_START_TAG = WebMapContextTags.VIEW_CONTEXT_0_1_4;
263
                                        parse1_1_0(file);
264
                                } else if (getVersion().equals("1.1.0")) {
265
                                        parse1_1_0(file);
266
                                } else if (getVersion().equals("1.0.0")) {
267
                                        parse1_1_0(file);
268
                                } else {
269
                                        parseDefaultVersion(file);
270
                                }
271

    
272
                                // Once parsed, check errors
273
                                if (errorMessages.length()>0) {
274
                                        throw new ImportMapContextException(errorMessages.toString(), false);
275
                                }
276
                        } else {
277
                                throw new UnsupportedVersionLayerException(file.getName(),null);
278
                        }
279
                }
280
        }
281

    
282

    
283
        /**
284
         * If no version was recognized then will parse the default one which is supposed
285
         * to be the best available.
286
         * @param file
287
         * @throws ImportMapContextException
288
         */
289
        private void parseDefaultVersion(File file) throws ImportMapContextException {
290
                parse1_1_0(file);
291
        }
292

    
293
        /**
294
         * Reads the header of the Weg Map Context file and determines which version
295
         * it belongs to.
296
         * @return String.
297
         */
298
        private String getVersion() {
299
                if (fileVersion == null) {
300
                        String v = null;
301
                        try {
302
                                FileReader fr = new FileReader(mapContextFile);
303
                                KXmlParser parser = new KXmlParser();
304
                                parser.setInput(fr);
305
                                parser.nextTag();
306
                            if ( parser.getEventType() != KXmlParser.END_DOCUMENT )        {
307
                                    if ((parser.getName().compareTo(WebMapContextTags.VIEW_CONTEXT) == 0) ||
308
                                             parser.getName().compareTo(WebMapContextTags.VIEW_CONTEXT_0_1_4) == 0) {
309
                                            v = parser.getAttributeValue("", WebMapContextTags.VERSION);
310
                                    }
311
                            }
312
                        } catch (FileNotFoundException fnfEx) {
313
                        } catch (XmlPullParserException xmlEx) {
314
                                xmlEx.printStackTrace();
315
                        } catch (IOException e) {
316
                        }
317
                        fileVersion = v;
318
                }
319
                return fileVersion;
320
        }
321

    
322
        /**
323
         * Reads a Web Map Context version 1.1.0. As far as v1.0.0 is a subset of
324
         * v1.1.0 it can be used to read files belonging to 1.0.0 as well.
325
         * @param file, the web map context file.
326
         */
327
        private void parse1_1_0(File file) throws ImportMapContextException{
328
                try {
329
                        FileReader fr;
330
                        try
331
                    {
332
                                fr = new FileReader(file);
333
                            BufferedReader br = new BufferedReader(fr);
334
                            char[] buffer = new char[100];
335
                            br.read(buffer);
336
                            StringBuffer st = new StringBuffer(new String(buffer));
337
                            String searchText = "encoding=\"";
338
                            int index = st.indexOf(searchText);
339
                            if (index>-1) {
340
                                    st.delete(0, index+searchText.length());
341
                                    encoding = st.substring(0, st.indexOf("\""));
342
                            }
343
                    } catch(FileNotFoundException ex)        {
344
                            ex.printStackTrace();
345
                    } catch (IOException e) {
346
                                e.printStackTrace();
347
                        }
348

    
349
                        fr = new FileReader(file);
350
                        KXmlParser parser = new KXmlParser();
351
                        parser.setInput(new FileInputStream(file), encoding);
352
                        int tag = parser.nextTag();
353
                        if ( parser.getEventType() != KXmlParser.END_DOCUMENT )
354
                        {
355
                                parser.require(KXmlParser.START_TAG, null, WMC_START_TAG);
356
                                while(tag != KXmlParser.END_DOCUMENT) {
357
                                        switch(tag) {
358
                                                case KXmlParser.START_TAG:
359
                                                        if (parser.getName().compareTo(WMC_START_TAG) == 0) {
360
                                                                id = parser.getAttributeValue("", WebMapContextTags.ID);
361
                                                                xmlns = parser.getAttributeValue("", WebMapContextTags.XMLNS);
362
                                                                xmlns_xlink = parser.getAttributeValue("", WebMapContextTags.XMLNS_XLINK);
363
                                                                xmlns_xsi = parser.getAttributeValue("", WebMapContextTags.XMLNS_XSI);
364
                                                                xsi_schemaLocation = parser.getAttributeValue("", WebMapContextTags.XSI_SCHEMA_LOCATION) ;
365
                                                        } else if (parser.getName().compareTo(WebMapContextTags.GENERAL) == 0) {
366
                                                                parseGeneral1_1_0(parser);
367
                                                        } else if (parser.getName().compareTo(WebMapContextTags.LAYER_LIST) == 0) {
368
                                                                int layerListTag = parser.nextTag();
369
                                                                boolean bLayerListEnd = false;
370
                                                                layerList = new ArrayList();
371
                                                                while (!bLayerListEnd) {
372
                                                                        switch(layerListTag) {
373
                                                                        case KXmlParser.START_TAG:
374
                                                                                if (parser.getName().compareTo(WebMapContextTags.LAYER) == 0) {
375
                                                                                        FLyrWMS layer = parseLayer1_1_0(parser);
376
                                                                                        // will use the mapcontext's bounding box as layer's fullextent
377
                                                                                        IProjection proj =  CRSFactory.getCRS(srs);
378
                                                                                        if (proj == null) {
379
                                                                                                // non supported srs, and cannot continue
380
                                                                                                String msg = PluginServices.getText(this, "unsupported_crs") +
381
                                                                                                                         " (" + srs + ")";
382
                                                                                                throw new ImportMapContextException(msg, true);
383
                                                                                        }
384
                                                                                        String[] availableSRS = layer.getSRS().split(",");
385
                                                                                        ICoordTrans ct = null;
386
                                                                                        String mySRS = null;
387
                                                                                        for (int i = 0; i < availableSRS.length; i++) {
388
                                                                                                mySRS = availableSRS[i];
389
                                                                                                IProjection dstProj = CRSFactory.getCRS(mySRS);
390
                                                                                                if (dstProj != null) {
391
                                                                                                        try{
392
                                                                                                                        ct = proj.getCT(dstProj);
393
                                                                                                                }catch(Exception e){
394
                                                                                                                        NotificationManager.showMessageError(e.getLocalizedMessage(), e);
395
                                                                                                                }
396
                                                                                                        if (mySRS.equals(srs)) {
397
                                                                                                                // this is the most suitable SRS,
398
                                                                                                                break;
399
                                                                                                        }
400
                                                                                                }
401
                                                                                        }
402

    
403
                                                                                        if (ct != null) {
404
                                                                                                // I've found a supported projection
405
                                                                                                layer.setFullExtent(ct.convert(bBox));
406
                                                                                                layer.setSRS(mySRS);
407
                                                                                        } else {
408
                                                                                                // can't reproject
409
                                                                                                errorMessages.append("[").
410
                                                                                                                      append(PluginServices.getText(this, "layer")).
411
                                                                                                                      append(" ").
412
                                                                                                                      append(layer.getName()).
413
                                                                                                                      append("] ").
414
                                                                                                                          append(PluginServices.getText(this, "cant_reproject_from_any_of")).
415
                                                                                                                          append(" [").append(layer.getSRS()).append("] ").
416
                                                                                                                          append(PluginServices.getText(this, "to")).
417
                                                                                                                          append(srs).
418
                                                                                                                          append("\n");
419

    
420
                                                                                                /*
421
                                                                                                 * will use view's projection and bounding box
422
                                                                                                 * strictly this is incorrect but, at least it allows
423
                                                                                                 * the user to recover by changin layer properties.
424
                                                                                                 */
425
                                                                                                layer.setFullExtent(bBox);
426
                                                                                                layer.setSRS(srs);
427
                                                                                        }
428

    
429
                                                                                        layer.setWmsTransparency(true);
430
                                                                                        layerList.add(layer);
431
                                                                                } else {
432
                                                                    System.out.println("Unrecognized "+parser.getName());
433
                                                                                }
434
                                                                                break;
435
                                                                        case KXmlParser.END_TAG:
436
                                                                                if (parser.getName().compareTo(WebMapContextTags.LAYER_LIST) == 0) {
437
                                                                                        bLayerListEnd = true;
438
                                                                                }
439
                                                                                break;
440
                                                                        case KXmlParser.TEXT:
441
                                                                                //System.out.println("[TEXT]["+kxmlParser.getText()+"]");
442
                                                                                break;
443
                                                                        }
444
                                                                        layerListTag = parser.next();
445
                                                                }
446
                                                        } else if (parser.getName().compareTo(WebMapContextTags.DIMENSION_LIST) == 0) {
447
                                                                // TODO
448
                                                                System.out.println("WebMapContext's Dimension not yet implemented");
449
                                                        } else {
450
                                            System.out.println("Unrecognized "+parser.getName());
451
                                                        }
452
                                                        break;
453
                                                case KXmlParser.END_TAG:
454
                                                        break;
455
                                                case KXmlParser.TEXT:
456
                                                        //System.out.println("[TEXT]["+kxmlParser.getText()+"]");
457
                                                        break;
458
                                        }
459
                                        tag = parser.next();
460
                                }
461
                                parser.require(KXmlParser.END_DOCUMENT, null, null);
462
                        }
463
                } catch (ImportMapContextException e){
464
                        throw e;
465
                } catch (Exception e) {
466
                        NotificationManager.addError(PluginServices.getText(this, "map_context_file_error"),e);
467
                        e.printStackTrace();
468
                }
469

    
470
        }
471

    
472
        /**
473
         * Parses the General tag of a web map context 1.1.0 (and 1.0.0) file
474
         * @param parser
475
         * @throws XmlPullParserException
476
         * @throws IOException
477
         */
478
        private void parseGeneral1_1_0(KXmlParser parser) throws XmlPullParserException, IOException {
479
                boolean end = false;
480
            int tag = parser.next();
481
            while (!end) {
482
                    switch(tag) {
483
                        case KXmlParser.START_TAG:
484
                                if (parser.getName().compareTo(WebMapContextTags.WINDOW) == 0) {
485
                                        if (windowSize == null) {
486
                                                        windowSize = new Dimension();
487
                                                }
488
                                                windowSize.setSize(Integer.parseInt(parser.getAttributeValue("", WebMapContextTags.WIDTH)),
489
                                                                                   Integer.parseInt(parser.getAttributeValue("", WebMapContextTags.HEIGHT)));
490
                                } else if (parser.getName().compareTo(WebMapContextTags.BOUNDING_BOX) == 0) {
491
                                        srs = parser.getAttributeValue("", WebMapContextTags.SRS);
492
                                        double minx = Double.parseDouble(parser.getAttributeValue("", WebMapContextTags.X_MIN));
493
                                        double miny = Double.parseDouble(parser.getAttributeValue("", WebMapContextTags.Y_MIN));
494
                                        double maxx = Double.parseDouble(parser.getAttributeValue("", WebMapContextTags.X_MAX));
495
                                        double maxy = Double.parseDouble(parser.getAttributeValue("", WebMapContextTags.Y_MAX));
496
                                        bBox = new Rectangle2D.Double(minx, miny, maxx-minx, maxy-miny);
497
                            } else if (parser.getName().compareTo(WebMapContextTags.TITLE) == 0) {
498
                                        title = parser.nextText();
499
                                } else if (parser.getName().compareTo(WebMapContextTags.ABSTRACT) == 0) {
500
                                        _abstract = parser.nextText();
501
                                } else if (parser.getName().compareTo(WebMapContextTags.KEYWORD_LIST) == 0) {
502
                                        keywordList = new ArrayList();
503
                                        boolean keywordEnd = false;
504
                                    int keywordTag = parser.next();
505
                                    while (!keywordEnd) {
506
                                            switch(keywordTag) {
507
                                                case KXmlParser.START_TAG:
508
                                                        if (parser.getName().compareTo(WebMapContextTags.KEYWORD) == 0) {
509
                                                                keywordList.add(parser.nextText());
510
                                                        } else {
511
                                                    System.out.println("Unrecognized "+parser.getName());
512
                                                                }
513
                                                                break;
514
                                                 case KXmlParser.END_TAG:
515
                                                        if (parser.getName().compareTo(WebMapContextTags.KEYWORD_LIST) == 0) {
516
                                                                                keywordEnd = true;
517
                                                                        }
518
                                                        break;
519
                                                case KXmlParser.TEXT:
520
                                                        if (parser.getName()!=null) {
521
                                                                                System.out.println("[TAG]["+parser.getName()+"]\n[TEXT]["+parser.getText().trim()+"]");
522
                                                                        }
523
                                                        break;
524
                                            }
525
                                            keywordTag = parser.next();
526
                                    }
527
                                } else if (parser.getName().compareTo(WebMapContextTags.LOGO_URL) == 0) {
528
                                        logoURLSize = new Dimension(Integer.parseInt(parser.getAttributeValue("", WebMapContextTags.WIDTH)),
529
                                                                                                Integer.parseInt(parser.getAttributeValue("", WebMapContextTags.HEIGHT)));
530
                                        logoURLFormat = parser.getAttributeValue("", WebMapContextTags.FORMAT.toLowerCase());
531
                                        parser.nextTag();
532
                                        if (parser.getName().compareTo(WebMapContextTags.ONLINE_RESOURCE) == 0) {
533
                                                logoURL = parser.getAttributeValue("", WebMapContextTags.XLINK_HREF);
534
                                        } else {
535
                                System.out.println("Unrecognized "+parser.getName());
536
                                            }
537
                                } else if (parser.getName().compareTo(WebMapContextTags.DESCRIPTION_URL) == 0) {
538
                                        descriptionURLFormat = parser.getAttributeValue("", WebMapContextTags.FORMAT.toLowerCase());
539
                                        parser.nextTag();
540
                                        if (parser.getName().compareTo(WebMapContextTags.ONLINE_RESOURCE) == 0) {
541
                                                descriptionURL = parser.getAttributeValue("", WebMapContextTags.XLINK_HREF);
542
                                        } else {
543
                                System.out.println("Unrecognized "+parser.getName());
544
                                            }
545
                                } else if (parser.getName().compareTo(WebMapContextTags.CONTACT_INFORMATION) == 0) {
546
                                        boolean contactInfoEnd = false;
547
                                    int contactInfoTag = parser.next();
548
                                    while (!contactInfoEnd) {
549
                                            switch(contactInfoTag) {
550
                                                case KXmlParser.START_TAG:
551
                                                        if (parser.getName().compareTo(WebMapContextTags.CONTACT_PERSON) == 0) {
552
                                                                contactPerson = parser.nextText();
553
                                                        } else if (parser.getName().compareTo(WebMapContextTags.CONTACT_ORGANIZATION) == 0) {
554
                                                                contactOrganization = parser.nextText();
555
                                                        } else if (parser.getName().compareTo(WebMapContextTags.CONTACT_POSITION) == 0) {
556
                                                                contactPosition = parser.nextText();
557
                                                        } else if (parser.getName().compareTo(WebMapContextTags.ADDRESS) == 0) {
558
                                                                address = parser.nextText();
559
                                                        } else if (parser.getName().compareTo(WebMapContextTags.CITY) == 0) {
560
                                                                city = parser.nextText();
561
                                                        } else if (parser.getName().compareTo(WebMapContextTags.STATE_OR_PROVINCE) == 0) {
562
                                                                stateOrProvince = parser.nextText();
563
                                                        } else if (parser.getName().compareTo(WebMapContextTags.POSTCODE) == 0) {
564
                                                                postCode = parser.nextText();
565
                                                        } else if (parser.getName().compareTo(WebMapContextTags.COUNTRY) == 0) {
566
                                                                country = parser.nextText();
567
                                                        } else if (parser.getName().compareTo(WebMapContextTags.CONTACT_VOICE_TELEPHONE) == 0) {
568
                                                                telephone = parser.nextText();
569
                                                        } else if (parser.getName().compareTo(WebMapContextTags.CONTACT_FACSIMILE_TELEPHONE) == 0) {
570
                                                                fax = parser.nextText();
571
                                                        } else if (parser.getName().compareTo(WebMapContextTags.CONTACT_ELECTRONIC_MAIL_ADDRESS) == 0) {
572
                                                                email = parser.nextText();
573
                                                        } else if (parser.getName().compareTo(WebMapContextTags.CONTACT_PERSON_PRIMARY) == 0) {
574
                                                                // DO NOTHING
575
                                                        } else if (parser.getName().compareTo(WebMapContextTags.CONTACT_ADDRESS) == 0) {
576
                                                                // DO NOTHING
577
                                                        } else {
578
                                                    System.out.println("Unrecognized "+parser.getName());
579
                                                                }
580
                                                        break;
581
                                                 case KXmlParser.END_TAG:
582
                                                        if (parser.getName().compareTo(WebMapContextTags.CONTACT_INFORMATION) == 0) {
583
                                                                                contactInfoEnd = true;
584
                                                                        }
585
                                                        break;
586
                                                case KXmlParser.TEXT:
587
                                                        if (parser.getName()!=null) {
588
                                                                                System.out.println("[TAG]["+parser.getName()+"]\n[TEXT]["+parser.getText().trim()+"]");
589
                                                                        }
590
                                                        break;
591
                                            }
592
                                            contactInfoTag = parser.next();
593
                                    }
594
                            } else {
595
                            System.out.println("Unrecognized "+parser.getName());
596
                                        }
597
                                        break;
598
                         case KXmlParser.END_TAG:
599
                                if (parser.getName().compareTo(WebMapContextTags.GENERAL) == 0) {
600
                                                end = true;
601
                                        }
602
                                break;
603
                        case KXmlParser.TEXT:
604
                                if (parser.getName()!=null) {
605
                                                System.out.println("[TAG]["+parser.getName()+"]\n[TEXT]["+parser.getText().trim()+"]");
606
                                        }
607
                                break;
608
                    }
609
                    tag = parser.next();
610
            }
611
        }
612

    
613
        private FLyrWMS parseLayer1_1_0(KXmlParser parser) throws XmlPullParserException, IOException {
614
                boolean end = false;
615
                FLyrWMS layer = new FLyrWMS();
616

    
617
                String queryable = parser.getAttributeValue("", WebMapContextTags.QUERYABLE);
618
                layer.setQueryable(queryable!=null && (queryable.equals("1") || queryable.toLowerCase().equals("true")));
619

    
620
                String hidden = parser.getAttributeValue("", WebMapContextTags.HIDDEN);
621
                layer.setVisible(hidden==null || !hidden.equals("1") || !hidden.toLowerCase().equals("true"));
622
            int tag = parser.next();
623
            while (!end) {
624
                    switch(tag) {
625
                        case KXmlParser.START_TAG:
626
                                if (parser.getName().compareTo(WebMapContextTags.SERVER) == 0) {
627
                                        String serverTitle = parser.getAttributeValue("", WebMapContextTags.TITLE.toLowerCase());
628
                                        parser.nextTag();
629
                                        if (parser.getName().compareTo(WebMapContextTags.ONLINE_RESOURCE) == 0) {
630
                                                layer.setHost(new URL(parser.getAttributeValue("", WebMapContextTags.XLINK_HREF)));
631
                                                if (serverTitles == null) {
632
                                                                serverTitles = new Hashtable();
633
                                                        }
634
                                            serverTitles.put(parser.getAttributeValue("", WebMapContextTags.XLINK_HREF), serverTitle);
635
                                        }
636
                                } else if (parser.getName().compareTo(WebMapContextTags.TITLE) == 0) {
637
                                        layer.setName(parser.nextText());
638
                                } else if (parser.getName().compareTo(WebMapContextTags.NAME) == 0) {
639
                                        layer.setLayerQuery(parser.nextText());
640
                                /* //TODO This case would handle nested layer definitions.
641
                                 *
642
                                 } else if (parser.getName().compareTo(WebMapContextTags.LAYER) == 0) {
643
                                        FLyrWMS sonLayer = parseLayer1_1_0(parser);
644
                                        String q = layer.getLayerQuery();
645
                                        if (q == null) q = "";
646
                                        else q += ",";
647
                                        layer.setLayerQuery( q + sonLayer.getLayerQuery());
648
                                 *
649
                                 */
650
                                } else if (parser.getName().compareTo(WebMapContextTags.ABSTRACT) == 0) {
651
                                        if (layerAbstracts == null) {
652
                                                        layerAbstracts = new Hashtable();
653
                                                }
654
                                        layerAbstracts.put(layer, parser.nextText());
655
                                } else if (parser.getName().compareTo(WebMapContextTags.SRS) == 0) {
656
                                        layer.setSRS(parser.nextText());
657
                                } else if (parser.getName().compareTo(WebMapContextTags.FORMAT_LIST) == 0) {
658
                                        int formatsTag = parser.nextTag();
659
                                        boolean bFormatsEnd = false;
660
                                        ArrayList formats = new ArrayList();
661
                                        while (!bFormatsEnd) {
662
                                                switch (formatsTag) {
663
                                                case KXmlParser.START_TAG:
664
                                                        if (parser.getName().compareTo(WebMapContextTags.FORMAT) == 0) {
665
                                                                String current = parser.getAttributeValue("", WebMapContextTags.CURRENT);
666
                                                                String format = parser.nextText();
667
                                                                if (current!=null && current.equals("1")) {
668
                                                                                layer.setFormat(format);
669
                                                                        }
670
                                                                formats.add(format);
671
                                                        } else {
672
                                                                System.out.println("Unrecognized "+parser.getName());
673
                                                        }
674
                                                        break;
675
                                                case KXmlParser.END_TAG:
676
                                                        if (parser.getName().compareTo(WebMapContextTags.FORMAT_LIST) == 0) {
677
                                                                        bFormatsEnd = true;
678
                                                                }
679
                                                        break;
680
                                                case KXmlParser.TEXT:
681
                                                        if (parser.getName()!=null) {
682
                                                                        System.out.println("[TAG]["+parser.getName()+"]\n[TEXT]["+parser.getText().trim()+"]");
683
                                                                }
684
                                                        break;
685
                                                }
686
                                                formatsTag = parser.next();
687
                                        }
688
                                        if (layerFormats == null) {
689
                                                        layerFormats = new Hashtable();
690
                                                }
691
                                        layerFormats.put(layer, formats.toArray(new String[0]));
692

    
693
                                } else if (parser.getName().compareTo(WebMapContextTags.STYLE_LIST) == 0) {
694
                                        int stylesTag = parser.nextTag();
695
                                        boolean bStylesEnd = false;
696
                                        ArrayList styles = new ArrayList();
697
                                        while (!bStylesEnd) {
698
                                                switch (stylesTag) {
699
                                                case KXmlParser.START_TAG:
700
                                                        if (parser.getName().compareTo(WebMapContextTags.STYLE) == 0) {
701
                                                                String current = parser.getAttributeValue("", WebMapContextTags.CURRENT);
702
                                                                FMapWMSStyle style = parseStyle1_1_0(parser);
703

    
704
                                                                if (current!=null && current.equals("1") && !style.name.equals("default")) {
705
                                                                        Vector v = new Vector();
706
                                                                        v.add(style.name);
707
                                                                        layer.setStyles(v);
708
                                                                }
709
                                                                styles.add(style);
710
                                                        } else {
711
                                                                System.out.println("Unrecognized "+parser.getName());
712
                                                        }
713
                                                        break;
714
                                                case KXmlParser.END_TAG:
715
                                                        if (parser.getName().compareTo(WebMapContextTags.STYLE_LIST) == 0) {
716
                                                                        bStylesEnd = true;
717
                                                                }
718
                                                        break;
719
                                                case KXmlParser.TEXT:
720
                                                        if (parser.getName()!=null) {
721
                                                                        System.out.println("[TAG]["+parser.getName()+"]\n[TEXT]["+parser.getText().trim()+"]");
722
                                                                }
723
                                                        break;
724
                                                }
725
                                                stylesTag = parser.next();
726
                                        }
727
                                        if (layerStyles == null) {
728
                                                        layerStyles = new Hashtable();
729
                                                }
730

    
731
                                        layerStyles.put(layer, styles.toArray(new FMapWMSStyle[0]));
732
                                } else {
733
                                        System.out.println("Unrecognized "+parser.getName());
734
                                }
735
                                break;
736
                        case KXmlParser.END_TAG:
737
                                if (parser.getName().compareTo(WebMapContextTags.LAYER) == 0) {
738
                                                end = true;
739
                                        }
740
                                break;
741
                        case KXmlParser.TEXT:
742
                                if (parser.getName()!=null) {
743
                                                System.out.println("[TAG]["+parser.getName()+"]\n[TEXT]["+parser.getText().trim()+"]");
744
                                        }
745
                                break;
746
                    }
747
                    tag = parser.next();
748
            }
749
            return layer;
750
        }
751

    
752
        private FMapWMSStyle parseStyle1_1_0(KXmlParser parser) throws XmlPullParserException, IOException {
753
                boolean end = false;
754
                String styleName = null;
755
                String styleAbstract = null;
756
                String styleTitle = null;
757
                int legendWidth = -1;
758
                int legendHeight = -1;
759
                String legendType = null;
760
                String legendHref = null;
761

    
762
            int tag = parser.next();
763
            while (!end) {
764
                    switch(tag) {
765
                        case KXmlParser.START_TAG:
766
                                if (parser.getName().compareTo(WebMapContextTags.NAME) == 0) {
767
                                        styleName = parser.nextText();
768
                                } else if (parser.getName().compareTo(WebMapContextTags.ABSTRACT) == 0) {
769
                                        styleAbstract = parser.nextText();
770
                                } else if (parser.getName().compareTo(WebMapContextTags.TITLE) == 0) {
771
                                        styleTitle = parser.nextText();
772
                                } else if (parser.getName().compareTo(WebMapContextTags.LEGEND_URL) == 0){
773
                                        legendWidth = Integer.parseInt(parser.getAttributeValue("", WebMapContextTags.WIDTH));
774
                                        legendHeight = Integer.parseInt(parser.getAttributeValue("", WebMapContextTags.HEIGHT));
775
                                        parser.nextTag();
776
                                        if (parser.getName().compareTo(WebMapContextTags.ONLINE_RESOURCE) == 0 ) {
777
                                                        legendType = parser.getAttributeValue("", WebMapContextTags.XLINK_TYPE);
778
                                                        legendHref = parser.getAttributeValue("", WebMapContextTags.XLINK_HREF);
779
                                        }
780
                                } else {
781
                            System.out.println("Unrecognized "+parser.getName());
782
                                        }
783
                                break;
784
                         case KXmlParser.END_TAG:
785
                                if (parser.getName().compareTo(WebMapContextTags.STYLE) == 0) {
786
                                                end = true;
787
                                        }
788
                                break;
789
                        case KXmlParser.TEXT:
790
                                if (parser.getName()!=null) {
791
                                                System.out.println("[TAG]["+parser.getName()+"]\n[TEXT]["+parser.getText().trim()+"]");
792
                                        }
793
                                break;
794
                    }
795
                    tag = parser.next();
796
            }
797
            WMSLayerNode n = new WMSLayerNode();
798
            FMapWMSStyle sty = n.new FMapWMSStyle();
799
            sty.name = styleName;
800
            sty.title = styleTitle;
801
            sty.styleAbstract = styleAbstract;
802
            sty.legendWidth = legendWidth;
803
            sty.legendHeight = legendHeight;
804
            sty.type = legendType;
805
            sty.href = legendHref;
806
            sty.parent = null;
807
            return sty;
808
        }
809

    
810
        /**
811
         * Creates the Web Map Context (WMC) XML according on the version 1.1.0. Since Web
812
         * WMC 1.0.0 is a subset of WMC 1.1.0 and this method does not produce tags for
813
         * unset values, it can be used to produce WMC 1.0.0, or even to produce
814
         * the deprecated (but still alive) WMC 0.1.4.
815
         * @param v
816
         * @return
817
         */
818
        @SuppressWarnings("unchecked")
819
        private String createMapContext1_1_0(DefaultViewDocument v) {
820
                ArrayList layersToExport = getExportableLayers(v);
821

    
822
                XmlBuilder xml = new XmlBuilder();
823
                HashMap xmlAttrs = new HashMap();
824
                xml.setEncoding("ISO-8859-1"); // TODO make it customizable???
825
                xml.writeHeader();
826

    
827
                // <ViewContext>
828
                String viewContextTag;
829
                if (fileVersion.equals("0.1.4")) {
830
                        viewContextTag = WebMapContextTags.VIEW_CONTEXT_0_1_4;
831
                } else {
832
                        viewContextTag = WebMapContextTags.VIEW_CONTEXT;
833
                }
834

    
835
                xml.writeRaw("<!-- "+PluginServices.getText(this, "created_with")+" gvSIG "+ ApplicationLocator.getManager().getVersion() +" -->");
836

    
837
                xmlAttrs.put(WebMapContextTags.VERSION, fileVersion);
838
                xmlAttrs.put(WebMapContextTags.ID, id);
839
                xmlAttrs.put(WebMapContextTags.XMLNS, WebMapContextTags.XMLNS_VALUE);
840
                xmlAttrs.put(WebMapContextTags.XMLNS_XLINK, WebMapContextTags.XMLNS_XLINK_VALUE);
841
                xmlAttrs.put(WebMapContextTags.XMLNS_XSI, WebMapContextTags.XMLNS_XSI_VALUE);
842
                xmlAttrs.put(WebMapContextTags.XSI_SCHEMA_LOCATION, WebMapContextTags.XSI_SCHEMA_LOCATION_VALUE);
843
                xml.openTag(viewContextTag,  xmlAttrs);
844
                xmlAttrs.clear();
845

    
846
                        // <General>
847
                        xml.openTag(WebMapContextTags.GENERAL);
848

    
849
                                // <Window>
850
                                if (windowSize!=null) {
851
                                        xmlAttrs.put(WebMapContextTags.WIDTH, ((int) windowSize.getWidth())+"");
852
                                        xmlAttrs.put(WebMapContextTags.HEIGHT, ((int) windowSize.getHeight())+"");
853
                                        xml.writeTag(WebMapContextTags.WINDOW, xmlAttrs);
854
                                        xmlAttrs.clear();
855
                                }
856
                                // </Window>
857

    
858
                                // <BoundingBox>
859
                                xmlAttrs.put(WebMapContextTags.SRS, v.getProjection().getAbrev());
860
                                xmlAttrs.put(WebMapContextTags.X_MIN, bBox.getMinX()+"");
861
                                xmlAttrs.put(WebMapContextTags.Y_MIN, bBox.getMinY()+"");
862
                                xmlAttrs.put(WebMapContextTags.X_MAX, bBox.getMaxX()+"");
863
                                xmlAttrs.put(WebMapContextTags.Y_MAX, bBox.getMaxY()+"");
864
                                xml.writeTag(WebMapContextTags.BOUNDING_BOX, xmlAttrs);
865
                                xmlAttrs.clear();
866
                                // </BoundingBox>
867

    
868
                                // <Title>
869
                                xml.writeTag(WebMapContextTags.TITLE, title.trim());
870
                                // </Title>
871

    
872
                                // <Abstract>
873
                                if (_abstract != null) {
874
                                        xml.writeTag(WebMapContextTags.ABSTRACT, _abstract.trim());
875
                                // </Abstract>
876
                                }
877

    
878
                                // <LogoURL>
879
                                if (logoURL != null) {
880
                                        xml.writeTag(WebMapContextTags.LOGO_URL, logoURL.trim());
881
                                // </LogoURL>
882
                                }
883

    
884
                                // <DescriptionURL>
885
                                if (descriptionURL != null) {
886
                                        xml.writeTag(WebMapContextTags.DESCRIPTION_URL, descriptionURL.trim());
887
                                // </DescriptionURL>
888
                                }
889

    
890
                                if (contactInfo) {
891

    
892
                                        // <ContactInformation>
893
                                        xml.openTag(WebMapContextTags.CONTACT_INFORMATION);
894
                                        if (contactPerson != null || contactOrganization != null) {
895

    
896
                                                // <ContactPersonPrimary>
897
                                                xml.openTag(WebMapContextTags.CONTACT_PERSON_PRIMARY);
898

    
899
                                                        // <ContactPerson>
900
                                                        if (contactPerson != null) {
901
                                                                xml.writeTag(WebMapContextTags.CONTACT_PERSON, contactPerson.trim());
902
                                                        // </ContactPerson>
903
                                                        }
904

    
905
                                                        // <ContactOrganization>
906
                                                        if (contactOrganization != null) {
907
                                                                xml.writeTag(WebMapContextTags.CONTACT_ORGANIZATION, contactOrganization.trim());
908
                                                        // </ContactOrganization>
909
                                                        }
910

    
911
                                                xml.closeTag();
912
                                                // </ContactPersonPrimary>
913
                                        }
914
                                        xml.closeTag();
915
                                        // </ContactInformation>
916

    
917
                                        // <ContactPosition>
918
                                        if (contactPosition != null) {
919
                                                xml.writeTag(WebMapContextTags.CONTACT_POSITION, contactPosition.trim());
920
                                        // </ContactPosition>
921
                                        }
922

    
923
                                        // <ContactAddress>
924
                                        if (address != null || city != null || stateOrProvince != null || postCode != null || country != null) {
925
                                                xml.openTag(WebMapContextTags.CONTACT_ADDRESS);
926

    
927
                                                        // <AddressType>
928
                                                        xml.writeTag(WebMapContextTags.ADDRESS_TYPE, "Postal");
929
                                                        // </AddressType>
930

    
931
                                                        // <Address>
932
                                                        if (address != null) {
933
                                                                xml.writeTag(WebMapContextTags.ADDRESS, address.trim());
934
                                                        // </Address>
935
                                                        }
936

    
937
                                                        // <City>
938
                                                        if (city != null) {
939
                                                                xml.writeTag(WebMapContextTags.CITY, city.trim());
940
                                                        // </City>
941
                                                        }
942

    
943
                                                        // <StateOrProvince>
944
                                                        if (stateOrProvince != null) {
945
                                                                xml.writeTag(WebMapContextTags.STATE_OR_PROVINCE, stateOrProvince.trim());
946
                                                        // </StateOrProvince>
947
                                                        }
948

    
949
                                                        // <PostCode>
950
                                                        if (postCode != null) {
951
                                                                xml.writeTag(WebMapContextTags.POSTCODE, postCode.trim());
952
                                                        // </PostCode>
953
                                                        }
954

    
955
                                                        // <Country>
956
                                                        if (country != null) {
957
                                                                xml.writeTag(WebMapContextTags.COUNTRY, country.trim());
958
                                                        }
959
                                                        // </Country>
960
                                                xml.closeTag();
961
                                        }
962
                                        // </ContactAddress>
963

    
964
                                        // <ContactVoiceTelephone>
965
                                        if (telephone != null) {
966
                                                xml.writeTag(WebMapContextTags.CONTACT_VOICE_TELEPHONE, telephone.trim());
967
                                        // </ContactVoiceTelephone>
968
                                        }
969

    
970
                                        // <ContactFacsimileTelephone>
971
                                        if (fax != null) {
972
                                                xml.writeTag(WebMapContextTags.CONTACT_FACSIMILE_TELEPHONE, fax.trim());
973
                                        // </ContactFacsimileTelephone>
974
                                        }
975

    
976
                                        // <ContactElectronicMailAddress>
977
                                        if (email != null) {
978
                                                xml.writeTag(WebMapContextTags.CONTACT_ELECTRONIC_MAIL_ADDRESS, email.trim());
979
                                        // </ContactElectronicMailAddress>
980
                                        }
981
                                }
982
                                // <KeywordList>
983
                                xml.openTag(WebMapContextTags.KEYWORD_LIST);
984
                                if (keywordList != null) {
985
                                        for (int i = 0; i < keywordList.size(); i++) {
986
                                                xml.writeTag(WebMapContextTags.KEYWORD, ((String) keywordList.get(i)).trim());
987
                                        }
988
                                } else {
989
                                        xml.writeTag(WebMapContextTags.KEYWORD, "");
990
                                }
991
                                xml.closeTag();
992

    
993
                                // </KeywordList>
994
                        xml.closeTag();
995
                        // </General>
996

    
997
                        // <LayerList>
998
                        xml.openTag(WebMapContextTags.LAYER_LIST);
999
                        for (int i = 0; i < layersToExport.size(); i++) {
1000
                                xml.writeRaw(((FLyrWMS) layersToExport.get(i)).toMapContext(fileVersion));
1001
                        }
1002
                        xml.closeTag();
1003
                        // </LayerList>
1004
                xml.closeTag();
1005
                // </ViewContext>
1006

    
1007
                return xml.getXML();
1008
        }
1009

    
1010
        /**
1011
         * Exports the ProjectView passed as parameter to Web Map Context XML compliant
1012
         * with the defined specifications for the version set in the fileVersion field.
1013
         * @param DefaultViewDocument to be exported
1014
         * @return String containing the XML
1015
         */
1016
        public String toXML(DefaultViewDocument v) {
1017
                if (fileVersion.equals("1.1.0") ||
1018
                                fileVersion.equals("1.0.0") ||
1019
                                fileVersion.equals("0.1.4")) {
1020
                        return createMapContext1_1_0(v);
1021
                }
1022
                return null;
1023
        }
1024

    
1025

    
1026
        public static ArrayList getExportableLayers(DefaultViewDocument v) {
1027
                ArrayList list = new ArrayList();
1028
                FLayers lyrs = v.getMapContext().getLayers();
1029
                list.addAll(_getExportableLayers(lyrs));
1030
                return list;
1031
        }
1032

    
1033
        private static ArrayList _getExportableLayers(FLayer lyr) {
1034
                ArrayList list = new ArrayList();
1035
                if (checkType(lyr)) {
1036
                        list.add(lyr);
1037
                } else {
1038
                        if (lyr instanceof FLayers) {
1039
                                FLayers lyrs = (FLayers) lyr;
1040
                                for (int i = 0; i < lyrs.getLayersCount(); i++) {
1041
                                        list.addAll(_getExportableLayers(lyrs.getLayer(i)));
1042
                                }
1043
                        }
1044
                }
1045
                return list;
1046
        }
1047

    
1048
        /**
1049
         * Checks if the layer is supported by the WebMapContext
1050
         * @param lyr
1051
         * @return
1052
         */
1053
        private static boolean checkType(FLayer lyr) {
1054
                return supportedLayers.contains(lyr.getClass());
1055
        }
1056

    
1057
        /**
1058
         * Searches in the layer tree of the TOC for an ocurrence of any
1059
         * exportable layer and returns true if so, or false otherwise.
1060
         * @param layer
1061
         * @return
1062
         */
1063
        public static boolean containsExportableLayers(FLayer layer) {
1064
                if (checkType(layer)) {
1065
                        return true;
1066
                }
1067

    
1068
                if (layer instanceof FLayers) {
1069
                        FLayers layers = (FLayers) layer;
1070
                        for (int i = 0; i < layers.getLayersCount(); i++) {
1071
                                FLayer lyr = layers.getLayer(i);
1072
                                if (containsExportableLayers(lyr)) {
1073
                                        return true;
1074
                                }
1075

    
1076
                        }
1077
                }
1078
                return false;
1079
        }
1080
}