001/* 002 * Copyright 2006 - 2013 003 * Stefan Balev <stefan.balev@graphstream-project.org> 004 * Julien Baudry <julien.baudry@graphstream-project.org> 005 * Antoine Dutot <antoine.dutot@graphstream-project.org> 006 * Yoann Pigné <yoann.pigne@graphstream-project.org> 007 * Guilhelm Savin <guilhelm.savin@graphstream-project.org> 008 * 009 * This file is part of GraphStream <http://graphstream-project.org>. 010 * 011 * GraphStream is a library whose purpose is to handle static or dynamic 012 * graph, create them from scratch, file or any source and display them. 013 * 014 * This program is free software distributed under the terms of two licenses, the 015 * CeCILL-C license that fits European law, and the GNU Lesser General Public 016 * License. You can use, modify and/ or redistribute the software under the terms 017 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following 018 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by 019 * the Free Software Foundation, either version 3 of the License, or (at your 020 * option) any later version. 021 * 022 * This program is distributed in the hope that it will be useful, but WITHOUT ANY 023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 024 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 025 * 026 * You should have received a copy of the GNU Lesser General Public License 027 * along with this program. If not, see <http://www.gnu.org/licenses/>. 028 * 029 * The fact that you are presently reading this means that you have had 030 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms. 031 */ 032package org.graphstream.stream.file; 033 034import java.io.IOException; 035import java.util.EnumMap; 036import java.util.HashMap; 037import java.util.LinkedList; 038import java.util.List; 039 040import javax.xml.stream.XMLStreamException; 041import javax.xml.stream.events.XMLEvent; 042 043/** 044 * Source to read GPX (GPS eXchange Format) data an XML extension to exchange 045 * gps coordinates, routes and tracks. 046 * 047 * Read more about GPX at <a 048 * href="https://en.wikipedia.org/wiki/GPS_eXchange_Format">Wikipedia</a> 049 * 050 */ 051public class FileSourceGPX extends FileSourceXML { 052 053 /** 054 * Parser used by this source. 055 */ 056 protected GPXParser parser; 057 058 /** 059 * Flag to set strict mode. 060 */ 061 protected boolean strict; 062 063 public FileSourceGPX() { 064 strict = false; 065 } 066 067 public void setStrict(boolean on) { 068 strict = on; 069 } 070 071 public boolean isStrict() { 072 return strict; 073 } 074 075 /* 076 * (non-Javadoc) 077 * 078 * @see org.graphstream.stream.file.FileSourceXML#afterStartDocument() 079 */ 080 protected void afterStartDocument() throws IOException, XMLStreamException { 081 parser = new GPXParser(); 082 parser.__gpx(); 083 } 084 085 /* 086 * (non-Javadoc) 087 * 088 * @see org.graphstream.stream.file.FileSourceXML#beforeEndDocument() 089 */ 090 protected void beforeEndDocument() throws IOException, XMLStreamException { 091 parser = null; 092 } 093 094 /* 095 * (non-Javadoc) 096 * 097 * @see org.graphstream.stream.file.FileSourceXML#nextEvents() 098 */ 099 public boolean nextEvents() throws IOException { 100 return false; 101 } 102 103 protected class WayPoint { 104 String name; 105 double lat, lon, ele; 106 HashMap<String, Object> attributes; 107 108 WayPoint() { 109 attributes = new HashMap<String, Object>(); 110 name = null; 111 lat = lon = ele = 0; 112 } 113 114 void deploy() { 115 sendNodeAdded(sourceId, name); 116 sendNodeAttributeAdded(sourceId, name, "xyz", new double[] { lon, 117 lat, ele }); 118 119 for (String key : attributes.keySet()) 120 sendNodeAttributeAdded(sourceId, name, key, attributes.get(key)); 121 } 122 } 123 124 protected class GPXParser extends Parser implements GPXConstants { 125 126 int automaticPointId; 127 int automaticRouteId; 128 int automaticEdgeId; 129 130 GPXParser() { 131 automaticRouteId = 0; 132 automaticPointId = 0; 133 automaticEdgeId = 0; 134 } 135 136 /** 137 * Base for read points since points can be one of "wpt", "rtept", 138 * "trkpt". 139 * 140 * @param elementName 141 * @return 142 * @throws IOException 143 * @throws XMLStreamException 144 */ 145 private WayPoint waypoint(String elementName) throws IOException, 146 XMLStreamException { 147 XMLEvent e; 148 WayPoint wp = new WayPoint(); 149 EnumMap<WPTAttribute, String> attributes; 150 LinkedList<String> links = new LinkedList<String>(); 151 152 e = getNextEvent(); 153 checkValid(e, XMLEvent.START_ELEMENT, elementName); 154 155 attributes = getAttributes(WPTAttribute.class, e.asStartElement()); 156 157 if (!attributes.containsKey(WPTAttribute.LAT)) { 158 XMLStreamException ex = newParseError(e, 159 "attribute 'lat' is required"); 160 161 if (strict) 162 throw ex; 163 else 164 ex.printStackTrace(); 165 } 166 167 if (!attributes.containsKey(WPTAttribute.LON)) { 168 XMLStreamException ex = newParseError(e, 169 "attribute 'lon' is required"); 170 171 if (strict) 172 throw ex; 173 else 174 ex.printStackTrace(); 175 } 176 177 wp.lat = Double.parseDouble(attributes.get(WPTAttribute.LAT)); 178 wp.lon = Double.parseDouble(attributes.get(WPTAttribute.LON)); 179 wp.ele = 0; 180 181 wp.attributes.put("lat", wp.lat); 182 wp.attributes.put("lon", wp.lon); 183 184 e = getNextEvent(); 185 186 if (isEvent(e, XMLEvent.START_ELEMENT, "ele")) { 187 pushback(e); 188 wp.ele = __ele(); 189 wp.attributes.put("ele", wp.ele); 190 191 e = getNextEvent(); 192 } 193 194 if (isEvent(e, XMLEvent.START_ELEMENT, "time")) { 195 pushback(e); 196 wp.attributes.put("time", __time()); 197 198 e = getNextEvent(); 199 } 200 201 if (isEvent(e, XMLEvent.START_ELEMENT, "magvar")) { 202 pushback(e); 203 wp.attributes.put("magvar", __magvar()); 204 205 e = getNextEvent(); 206 } 207 208 if (isEvent(e, XMLEvent.START_ELEMENT, "geoidheight")) { 209 pushback(e); 210 wp.attributes.put("geoidheight", __geoidheight()); 211 212 e = getNextEvent(); 213 } 214 215 if (isEvent(e, XMLEvent.START_ELEMENT, "name")) { 216 pushback(e); 217 wp.name = __name(); 218 219 e = getNextEvent(); 220 } 221 222 if (isEvent(e, XMLEvent.START_ELEMENT, "cmt")) { 223 pushback(e); 224 wp.attributes.put("cmt", __cmt()); 225 226 e = getNextEvent(); 227 } 228 229 if (isEvent(e, XMLEvent.START_ELEMENT, "desc")) { 230 pushback(e); 231 wp.attributes.put("desc", __desc()); 232 233 e = getNextEvent(); 234 } 235 236 if (isEvent(e, XMLEvent.START_ELEMENT, "src")) { 237 pushback(e); 238 wp.attributes.put("src", __src()); 239 240 e = getNextEvent(); 241 } 242 243 while (isEvent(e, XMLEvent.START_ELEMENT, "link")) { 244 pushback(e); 245 links.add(__link()); 246 247 e = getNextEvent(); 248 } 249 250 wp.attributes.put("link", links.toArray(new String[links.size()])); 251 252 if (isEvent(e, XMLEvent.START_ELEMENT, "sym")) { 253 pushback(e); 254 wp.attributes.put("sym", __sym()); 255 256 e = getNextEvent(); 257 } 258 259 if (isEvent(e, XMLEvent.START_ELEMENT, "type")) { 260 pushback(e); 261 wp.attributes.put("type", __type()); 262 263 e = getNextEvent(); 264 } 265 266 if (isEvent(e, XMLEvent.START_ELEMENT, "fix")) { 267 pushback(e); 268 wp.attributes.put("fix", __fix()); 269 270 e = getNextEvent(); 271 } 272 273 if (isEvent(e, XMLEvent.START_ELEMENT, "sat")) { 274 pushback(e); 275 wp.attributes.put("sat", __sat()); 276 277 e = getNextEvent(); 278 } 279 280 if (isEvent(e, XMLEvent.START_ELEMENT, "hdop")) { 281 pushback(e); 282 wp.attributes.put("hdop", __hdop()); 283 284 e = getNextEvent(); 285 } 286 287 if (isEvent(e, XMLEvent.START_ELEMENT, "vdop")) { 288 pushback(e); 289 wp.attributes.put("vdop", __vdop()); 290 291 e = getNextEvent(); 292 } 293 294 if (isEvent(e, XMLEvent.START_ELEMENT, "pdop")) { 295 pushback(e); 296 wp.attributes.put("pdop", __pdop()); 297 298 e = getNextEvent(); 299 } 300 301 if (isEvent(e, XMLEvent.START_ELEMENT, "ageofdgpsdata")) { 302 pushback(e); 303 wp.attributes.put("ageofdgpsdata", __ageofdgpsdata()); 304 305 e = getNextEvent(); 306 } 307 308 if (isEvent(e, XMLEvent.START_ELEMENT, "dgpsid")) { 309 pushback(e); 310 wp.attributes.put("dgpsid", __dgpsid()); 311 312 e = getNextEvent(); 313 } 314 315 if (isEvent(e, XMLEvent.START_ELEMENT, "extensions")) { 316 pushback(e); 317 __extensions(); 318 319 e = getNextEvent(); 320 } 321 322 checkValid(e, XMLEvent.END_ELEMENT, elementName); 323 324 if (wp.name == null) 325 wp.name = String.format("wp#%08x", automaticPointId++); 326 327 return wp; 328 } 329 330 /** 331 * <pre> 332 * name : GPX 333 * attributes : GPXAttribute 334 * structure : METADATA? WPT* RTE* TRK* EXTENSIONS? 335 * </pre> 336 * 337 * @throws IOException 338 * @throws XMLStreamException 339 */ 340 private void __gpx() throws IOException, XMLStreamException { 341 XMLEvent e; 342 EnumMap<GPXAttribute, String> attributes; 343 344 e = getNextEvent(); 345 checkValid(e, XMLEvent.START_ELEMENT, "gpx"); 346 347 attributes = getAttributes(GPXAttribute.class, e.asStartElement()); 348 349 if (!attributes.containsKey(GPXAttribute.VERSION)) { 350 XMLStreamException ex = newParseError(e, 351 "attribute 'version' is required"); 352 353 if (strict) 354 throw ex; 355 else 356 ex.printStackTrace(); 357 } else { 358 sendGraphAttributeAdded(sourceId, "gpx.version", attributes 359 .get(GPXAttribute.VERSION)); 360 } 361 362 if (!attributes.containsKey(GPXAttribute.CREATOR)) { 363 XMLStreamException ex = newParseError(e, 364 "attribute 'creator' is required"); 365 366 if (strict) 367 throw ex; 368 else 369 ex.printStackTrace(); 370 } else { 371 sendGraphAttributeAdded(sourceId, "gpx.creator", attributes 372 .get(GPXAttribute.CREATOR)); 373 } 374 375 e = getNextEvent(); 376 377 if (isEvent(e, XMLEvent.START_ELEMENT, "metadata")) { 378 pushback(e); 379 __metadata(); 380 381 e = getNextEvent(); 382 } 383 384 while (isEvent(e, XMLEvent.START_ELEMENT, "wpt")) { 385 pushback(e); 386 __wpt(); 387 388 e = getNextEvent(); 389 } 390 391 while (isEvent(e, XMLEvent.START_ELEMENT, "rte")) { 392 pushback(e); 393 __rte(); 394 395 e = getNextEvent(); 396 } 397 398 while (isEvent(e, XMLEvent.START_ELEMENT, "trk")) { 399 pushback(e); 400 __trk(); 401 402 e = getNextEvent(); 403 } 404 405 if (isEvent(e, XMLEvent.START_ELEMENT, "extensions")) { 406 pushback(e); 407 __extensions(); 408 409 e = getNextEvent(); 410 } 411 412 checkValid(e, XMLEvent.END_ELEMENT, "gpx"); 413 } 414 415 /** 416 * <pre> 417 * name : METADATA 418 * attributes : 419 * structure : NAME? DESC? AUTHOR? COPYRIGHT? LINK* TIME? KEYWORDS? BOUNDS? EXTENSIONS? 420 * </pre> 421 * 422 * @throws IOException 423 * @throws XMLStreamException 424 */ 425 private void __metadata() throws IOException, XMLStreamException { 426 XMLEvent e; 427 428 e = getNextEvent(); 429 checkValid(e, XMLEvent.START_ELEMENT, "metadata"); 430 431 e = getNextEvent(); 432 433 if (isEvent(e, XMLEvent.START_ELEMENT, "name")) { 434 pushback(e); 435 sendGraphAttributeAdded(sourceId, "gpx.metadata.name", __name()); 436 437 e = getNextEvent(); 438 } 439 440 if (isEvent(e, XMLEvent.START_ELEMENT, "desc")) { 441 pushback(e); 442 sendGraphAttributeAdded(sourceId, "gpx.metadata.desc", __desc()); 443 444 e = getNextEvent(); 445 } 446 447 if (isEvent(e, XMLEvent.START_ELEMENT, "author")) { 448 pushback(e); 449 sendGraphAttributeAdded(sourceId, "gpx.metadata.author", 450 __author()); 451 452 e = getNextEvent(); 453 } 454 455 if (isEvent(e, XMLEvent.START_ELEMENT, "copyright")) { 456 pushback(e); 457 sendGraphAttributeAdded(sourceId, "gpx.metadata.copyright", 458 __copyright()); 459 460 e = getNextEvent(); 461 } 462 463 LinkedList<String> links = new LinkedList<String>(); 464 465 while (isEvent(e, XMLEvent.START_ELEMENT, "link")) { 466 pushback(e); 467 links.add(__link()); 468 469 e = getNextEvent(); 470 } 471 472 if (links.size() > 0) 473 sendGraphAttributeAdded(sourceId, "gpx.metadata.links", links 474 .toArray(new String[links.size()])); 475 476 if (isEvent(e, XMLEvent.START_ELEMENT, "time")) { 477 pushback(e); 478 sendGraphAttributeAdded(sourceId, "gpx.metadata.time", __time()); 479 480 e = getNextEvent(); 481 } 482 483 if (isEvent(e, XMLEvent.START_ELEMENT, "keywords")) { 484 pushback(e); 485 sendGraphAttributeAdded(sourceId, "gpx.metadata.keywords", 486 __keywords()); 487 488 e = getNextEvent(); 489 } 490 491 if (isEvent(e, XMLEvent.START_ELEMENT, "bounds")) { 492 pushback(e); 493 __bounds(); 494 495 e = getNextEvent(); 496 } 497 498 if (isEvent(e, XMLEvent.START_ELEMENT, "extensions")) { 499 pushback(e); 500 __extensions(); 501 502 e = getNextEvent(); 503 } 504 505 checkValid(e, XMLEvent.END_ELEMENT, "metadata"); 506 } 507 508 /** 509 * <pre> 510 * name : WPT 511 * attributes : WPTAttribute 512 * structure : ELE? TIME? MAGVAR? GEOIDHEIGHT? NAME? CMT? DESC? SRC? LINK* SYM? TYPE? FIX? SAT? HDOP? VDOP? PDOP? AGEOFDGPSDATA? DGPSID? EXTENSIONS? 513 * </pre> 514 * 515 * @throws IOException 516 * @throws XMLStreamException 517 */ 518 private void __wpt() throws IOException, XMLStreamException { 519 WayPoint wp = waypoint("wpt"); 520 wp.deploy(); 521 } 522 523 /** 524 * <pre> 525 * name : RTE 526 * attributes : 527 * structure : NAME? CMT? DESC? SRC? LINK* NUMBER? TYPE? EXTENSIONS? RTEPT* 528 * </pre> 529 * 530 * @throws IOException 531 * @throws XMLStreamException 532 */ 533 private void __rte() throws IOException, XMLStreamException { 534 XMLEvent e; 535 String name, cmt, desc, src, type, time; 536 int number; 537 LinkedList<String> links = new LinkedList<String>(); 538 LinkedList<WayPoint> points = new LinkedList<WayPoint>(); 539 540 name = cmt = desc = src = type = time = null; 541 number = -1; 542 543 e = getNextEvent(); 544 checkValid(e, XMLEvent.START_ELEMENT, "rte"); 545 546 e = getNextEvent(); 547 548 if (isEvent(e, XMLEvent.START_ELEMENT, "name")) { 549 pushback(e); 550 name = __name(); 551 552 e = getNextEvent(); 553 } 554 555 if (isEvent(e, XMLEvent.START_ELEMENT, "time")) { 556 pushback(e); 557 time = __time(); 558 559 e = getNextEvent(); 560 } 561 562 if (isEvent(e, XMLEvent.START_ELEMENT, "cmt")) { 563 pushback(e); 564 cmt = __cmt(); 565 566 e = getNextEvent(); 567 } 568 569 if (isEvent(e, XMLEvent.START_ELEMENT, "desc")) { 570 pushback(e); 571 desc = __desc(); 572 573 e = getNextEvent(); 574 } 575 576 if (isEvent(e, XMLEvent.START_ELEMENT, "src")) { 577 pushback(e); 578 src = __src(); 579 580 e = getNextEvent(); 581 } 582 583 while (isEvent(e, XMLEvent.START_ELEMENT, "link")) { 584 pushback(e); 585 links.add(__link()); 586 587 e = getNextEvent(); 588 } 589 590 if (isEvent(e, XMLEvent.START_ELEMENT, "number")) { 591 pushback(e); 592 number = __number(); 593 594 e = getNextEvent(); 595 } 596 597 if (isEvent(e, XMLEvent.START_ELEMENT, "type")) { 598 pushback(e); 599 type = __type(); 600 601 e = getNextEvent(); 602 } 603 604 if (isEvent(e, XMLEvent.START_ELEMENT, "extensions")) { 605 pushback(e); 606 __extensions(); 607 608 e = getNextEvent(); 609 } 610 611 while (isEvent(e, XMLEvent.START_ELEMENT, "rtept")) { 612 pushback(e); 613 points.addLast(__rtept()); 614 615 e = getNextEvent(); 616 } 617 618 checkValid(e, XMLEvent.END_ELEMENT, "rte"); 619 620 if (name == null) 621 name = String.format("route#%08x", automaticRouteId++); 622 623 sendGraphAttributeAdded(sourceId, "routes." + name, Boolean.TRUE); 624 sendGraphAttributeAdded(sourceId, "routes." + name + ".desc", desc); 625 sendGraphAttributeAdded(sourceId, "routes." + name + ".cmt", cmt); 626 sendGraphAttributeAdded(sourceId, "routes." + name + ".src", src); 627 sendGraphAttributeAdded(sourceId, "routes." + name + ".type", type); 628 sendGraphAttributeAdded(sourceId, "routes." + name + ".time", time); 629 sendGraphAttributeAdded(sourceId, "routes." + name + ".number", 630 number); 631 632 for (int i = 0; i < points.size(); i++) { 633 points.get(i).deploy(); 634 635 if (i > 0) { 636 String eid = String.format("seg#%08x", automaticEdgeId++); 637 sendEdgeAdded(sourceId, eid, points.get(i - 1).name, points 638 .get(i).name, true); 639 sendEdgeAttributeAdded(sourceId, eid, "route", name); 640 } 641 } 642 } 643 644 /** 645 * <pre> 646 * name : TRK 647 * attributes : 648 * structure : NAME? CMT? DESC? SRC? LINK* NUMBER? TYPE? EXTENSIONS? TRKSEG* 649 * </pre> 650 * 651 * @throws IOException 652 * @throws XMLStreamException 653 */ 654 private void __trk() throws IOException, XMLStreamException { 655 XMLEvent e; 656 String name, cmt, desc, src, type, time; 657 int number; 658 LinkedList<String> links = new LinkedList<String>(); 659 660 name = cmt = desc = src = type = time = null; 661 number = -1; 662 663 e = getNextEvent(); 664 checkValid(e, XMLEvent.START_ELEMENT, "trk"); 665 666 e = getNextEvent(); 667 668 if (isEvent(e, XMLEvent.START_ELEMENT, "name")) { 669 pushback(e); 670 name = __name(); 671 672 e = getNextEvent(); 673 } 674 675 if (isEvent(e, XMLEvent.START_ELEMENT, "time")) { 676 pushback(e); 677 time = __time(); 678 679 e = getNextEvent(); 680 } 681 682 if (isEvent(e, XMLEvent.START_ELEMENT, "cmt")) { 683 pushback(e); 684 cmt = __cmt(); 685 686 e = getNextEvent(); 687 } 688 689 if (isEvent(e, XMLEvent.START_ELEMENT, "desc")) { 690 pushback(e); 691 desc = __desc(); 692 693 e = getNextEvent(); 694 } 695 696 if (isEvent(e, XMLEvent.START_ELEMENT, "src")) { 697 pushback(e); 698 src = __src(); 699 700 e = getNextEvent(); 701 } 702 703 while (isEvent(e, XMLEvent.START_ELEMENT, "link")) { 704 pushback(e); 705 links.add(__link()); 706 707 e = getNextEvent(); 708 } 709 710 if (isEvent(e, XMLEvent.START_ELEMENT, "number")) { 711 pushback(e); 712 number = __number(); 713 714 e = getNextEvent(); 715 } 716 717 if (isEvent(e, XMLEvent.START_ELEMENT, "type")) { 718 pushback(e); 719 type = __type(); 720 721 e = getNextEvent(); 722 } 723 724 if (isEvent(e, XMLEvent.START_ELEMENT, "extensions")) { 725 pushback(e); 726 __extensions(); 727 728 e = getNextEvent(); 729 } 730 731 if (name == null) 732 name = String.format("route#%08x", automaticRouteId++); 733 734 sendGraphAttributeAdded(sourceId, "tracks." + name, Boolean.TRUE); 735 sendGraphAttributeAdded(sourceId, "tracks." + name + ".desc", desc); 736 sendGraphAttributeAdded(sourceId, "tracks." + name + ".cmt", cmt); 737 sendGraphAttributeAdded(sourceId, "tracks." + name + ".src", src); 738 sendGraphAttributeAdded(sourceId, "tracks." + name + ".type", type); 739 sendGraphAttributeAdded(sourceId, "tracks." + name + ".time", time); 740 sendGraphAttributeAdded(sourceId, "tracks." + name + ".number", 741 number); 742 743 while (isEvent(e, XMLEvent.START_ELEMENT, "trkseg")) { 744 pushback(e); 745 List<WayPoint> wps = __trkseg(); 746 747 for (int i = 0; i < wps.size(); i++) { 748 wps.get(i).deploy(); 749 750 if (i > 0) { 751 String eid = String.format("seg#%08x", 752 automaticEdgeId++); 753 sendEdgeAdded(sourceId, eid, wps.get(i - 1).name, wps 754 .get(i).name, true); 755 sendEdgeAttributeAdded(sourceId, eid, "route", name); 756 } 757 } 758 759 e = getNextEvent(); 760 } 761 762 checkValid(e, XMLEvent.END_ELEMENT, "trk"); 763 } 764 765 /** 766 * <pre> 767 * name : EXTENSIONS 768 * attributes : 769 * structure : 770 * </pre> 771 * 772 * @throws IOException 773 * @throws XMLStreamException 774 */ 775 private void __extensions() throws IOException, XMLStreamException { 776 XMLEvent e; 777 int stack = 0; 778 779 e = getNextEvent(); 780 checkValid(e, XMLEvent.START_ELEMENT, "extensions"); 781 782 e = getNextEvent(); 783 784 while (!(isEvent(e, XMLEvent.END_ELEMENT, "extensions") && stack == 0)) { 785 if (isEvent(e, XMLEvent.END_ELEMENT, "extensions")) 786 stack--; 787 else if (isEvent(e, XMLEvent.START_ELEMENT, "extensions")) 788 stack++; 789 790 e = getNextEvent(); 791 } 792 } 793 794 /** 795 * <pre> 796 * name : NAME 797 * attributes : 798 * structure : string 799 * </pre> 800 * 801 * @throws IOException 802 * @throws XMLStreamException 803 */ 804 private String __name() throws IOException, XMLStreamException { 805 String name; 806 XMLEvent e; 807 808 e = getNextEvent(); 809 checkValid(e, XMLEvent.START_ELEMENT, "name"); 810 811 name = __characters(); 812 813 e = getNextEvent(); 814 checkValid(e, XMLEvent.END_ELEMENT, "name"); 815 816 return name; 817 } 818 819 /** 820 * <pre> 821 * name : DESC 822 * attributes : 823 * structure : string 824 * </pre> 825 * 826 * @throws IOException 827 * @throws XMLStreamException 828 */ 829 private String __desc() throws IOException, XMLStreamException { 830 String desc; 831 XMLEvent e; 832 833 e = getNextEvent(); 834 checkValid(e, XMLEvent.START_ELEMENT, "desc"); 835 836 desc = __characters(); 837 838 e = getNextEvent(); 839 checkValid(e, XMLEvent.END_ELEMENT, "desc"); 840 841 return desc; 842 } 843 844 /** 845 * <pre> 846 * name : AUTHOR 847 * attributes : 848 * structure : NAME? EMAIL? LINK? 849 * </pre> 850 * 851 * @throws IOException 852 * @throws XMLStreamException 853 */ 854 private String __author() throws IOException, XMLStreamException { 855 String author = ""; 856 XMLEvent e; 857 858 e = getNextEvent(); 859 checkValid(e, XMLEvent.START_ELEMENT, "author"); 860 861 e = getNextEvent(); 862 863 if (isEvent(e, XMLEvent.START_ELEMENT, "name")) { 864 pushback(e); 865 author += __name(); 866 867 e = getNextEvent(); 868 } 869 870 if (isEvent(e, XMLEvent.START_ELEMENT, "email")) { 871 pushback(e); 872 author += " <" + __email() + ">"; 873 874 e = getNextEvent(); 875 } 876 877 if (isEvent(e, XMLEvent.START_ELEMENT, "link")) { 878 pushback(e); 879 author += " (" + __link() + ")"; 880 881 e = getNextEvent(); 882 } 883 884 e = getNextEvent(); 885 checkValid(e, XMLEvent.END_ELEMENT, "author"); 886 887 return author; 888 } 889 890 /** 891 * <pre> 892 * name : COPYRIGHT 893 * attributes : COPYRIGHTAttribute 894 * structure : YEAR? LICENCE? 895 * </pre> 896 * 897 * @throws IOException 898 * @throws XMLStreamException 899 */ 900 private String __copyright() throws IOException, XMLStreamException { 901 String copyright; 902 XMLEvent e; 903 EnumMap<COPYRIGHTAttribute, String> attributes; 904 905 e = getNextEvent(); 906 checkValid(e, XMLEvent.START_ELEMENT, "copyright"); 907 908 attributes = getAttributes(COPYRIGHTAttribute.class, e 909 .asStartElement()); 910 911 if (!attributes.containsKey(COPYRIGHTAttribute.AUTHOR)) { 912 XMLStreamException ex = newParseError(e, 913 "attribute 'author' is required"); 914 915 if (strict) 916 throw ex; 917 else 918 ex.printStackTrace(); 919 920 copyright = "unknown"; 921 } else 922 copyright = attributes.get(COPYRIGHTAttribute.AUTHOR); 923 924 e = getNextEvent(); 925 926 if (isEvent(e, XMLEvent.START_ELEMENT, "year")) { 927 pushback(e); 928 copyright += " " + __year(); 929 930 e = getNextEvent(); 931 } 932 933 if (isEvent(e, XMLEvent.START_ELEMENT, "license")) { 934 pushback(e); 935 copyright += " " + __license(); 936 937 e = getNextEvent(); 938 } 939 940 checkValid(e, XMLEvent.END_ELEMENT, "copyright"); 941 942 return copyright; 943 } 944 945 /** 946 * <pre> 947 * name : LINK 948 * attributes : LINKAttribute 949 * structure : TEXT? TYPE? 950 * </pre> 951 * 952 * @throws IOException 953 * @throws XMLStreamException 954 */ 955 private String __link() throws IOException, XMLStreamException { 956 String link; 957 XMLEvent e; 958 EnumMap<LINKAttribute, String> attributes; 959 960 e = getNextEvent(); 961 checkValid(e, XMLEvent.START_ELEMENT, "link"); 962 963 attributes = getAttributes(LINKAttribute.class, e.asStartElement()); 964 965 if (!attributes.containsKey(LINKAttribute.HREF)) { 966 XMLStreamException ex = newParseError(e, 967 "attribute 'href' is required"); 968 969 if (strict) 970 throw ex; 971 else 972 ex.printStackTrace(); 973 974 link = "unknown"; 975 } else 976 link = attributes.get(LINKAttribute.HREF); 977 978 e = getNextEvent(); 979 980 if (isEvent(e, XMLEvent.START_ELEMENT, "text")) { 981 pushback(e); 982 __text(); 983 984 e = getNextEvent(); 985 } 986 987 if (isEvent(e, XMLEvent.START_ELEMENT, "type")) { 988 pushback(e); 989 __type(); 990 991 e = getNextEvent(); 992 } 993 994 checkValid(e, XMLEvent.END_ELEMENT, "link"); 995 996 return link; 997 } 998 999 /** 1000 * <pre> 1001 * name : TIME 1002 * attributes : 1003 * structure : string 1004 * </pre> 1005 * 1006 * @throws IOException 1007 * @throws XMLStreamException 1008 */ 1009 private String __time() throws IOException, XMLStreamException { 1010 String time; 1011 XMLEvent e; 1012 1013 e = getNextEvent(); 1014 checkValid(e, XMLEvent.START_ELEMENT, "time"); 1015 1016 time = __characters(); 1017 1018 e = getNextEvent(); 1019 checkValid(e, XMLEvent.END_ELEMENT, "time"); 1020 1021 return time; 1022 } 1023 1024 /** 1025 * <pre> 1026 * name : KEYWORDS 1027 * attributes : 1028 * structure : string 1029 * </pre> 1030 * 1031 * @throws IOException 1032 * @throws XMLStreamException 1033 */ 1034 private String __keywords() throws IOException, XMLStreamException { 1035 String keywords; 1036 XMLEvent e; 1037 1038 e = getNextEvent(); 1039 checkValid(e, XMLEvent.START_ELEMENT, "keywords"); 1040 1041 keywords = __characters(); 1042 1043 e = getNextEvent(); 1044 checkValid(e, XMLEvent.END_ELEMENT, "keywords"); 1045 1046 return keywords; 1047 } 1048 1049 /** 1050 * <pre> 1051 * name : BOUNDS 1052 * attributes : BOUNDSAttribute 1053 * structure : 1054 * </pre> 1055 * 1056 * @throws IOException 1057 * @throws XMLStreamException 1058 */ 1059 private void __bounds() throws IOException, XMLStreamException { 1060 XMLEvent e; 1061 EnumMap<BOUNDSAttribute, String> attributes; 1062 double minlat, maxlat, minlon, maxlon; 1063 1064 e = getNextEvent(); 1065 checkValid(e, XMLEvent.START_ELEMENT, "bounds"); 1066 1067 attributes = getAttributes(BOUNDSAttribute.class, e 1068 .asStartElement()); 1069 1070 if (!attributes.containsKey(BOUNDSAttribute.MINLAT)) { 1071 XMLStreamException ex = newParseError(e, 1072 "attribute 'minlat' is required"); 1073 1074 if (strict) 1075 throw ex; 1076 else 1077 ex.printStackTrace(); 1078 } 1079 1080 if (!attributes.containsKey(BOUNDSAttribute.MAXLAT)) { 1081 XMLStreamException ex = newParseError(e, 1082 "attribute 'maxlat' is required"); 1083 1084 if (strict) 1085 throw ex; 1086 else 1087 ex.printStackTrace(); 1088 } 1089 1090 if (!attributes.containsKey(BOUNDSAttribute.MINLON)) { 1091 XMLStreamException ex = newParseError(e, 1092 "attribute 'minlon' is required"); 1093 1094 if (strict) 1095 throw ex; 1096 else 1097 ex.printStackTrace(); 1098 } 1099 1100 if (!attributes.containsKey(BOUNDSAttribute.MAXLON)) { 1101 XMLStreamException ex = newParseError(e, 1102 "attribute 'maxlon' is required"); 1103 1104 if (strict) 1105 throw ex; 1106 else 1107 ex.printStackTrace(); 1108 } 1109 1110 minlat = Double.parseDouble(attributes.get(BOUNDSAttribute.MINLAT)); 1111 maxlat = Double.parseDouble(attributes.get(BOUNDSAttribute.MAXLAT)); 1112 minlon = Double.parseDouble(attributes.get(BOUNDSAttribute.MINLON)); 1113 maxlon = Double.parseDouble(attributes.get(BOUNDSAttribute.MAXLON)); 1114 1115 sendGraphAttributeAdded(sourceId, "gpx.bounds", new double[] { 1116 minlat, minlon, maxlat, maxlon }); 1117 1118 e = getNextEvent(); 1119 checkValid(e, XMLEvent.END_ELEMENT, "bounds"); 1120 } 1121 1122 /** 1123 * <pre> 1124 * name : ELE 1125 * attributes : 1126 * structure : double 1127 * </pre> 1128 * 1129 * @throws IOException 1130 * @throws XMLStreamException 1131 */ 1132 private double __ele() throws IOException, XMLStreamException { 1133 String ele; 1134 XMLEvent e; 1135 1136 e = getNextEvent(); 1137 checkValid(e, XMLEvent.START_ELEMENT, "ele"); 1138 1139 ele = __characters(); 1140 1141 e = getNextEvent(); 1142 checkValid(e, XMLEvent.END_ELEMENT, "ele"); 1143 1144 return Double.parseDouble(ele); 1145 } 1146 1147 /** 1148 * <pre> 1149 * name : MAGVAR 1150 * attributes : 1151 * structure : double in [0,360] 1152 * </pre> 1153 * 1154 * @throws IOException 1155 * @throws XMLStreamException 1156 */ 1157 private double __magvar() throws IOException, XMLStreamException { 1158 String magvar; 1159 XMLEvent e; 1160 1161 e = getNextEvent(); 1162 checkValid(e, XMLEvent.START_ELEMENT, "magvar"); 1163 1164 magvar = __characters(); 1165 1166 e = getNextEvent(); 1167 checkValid(e, XMLEvent.END_ELEMENT, "magvar"); 1168 1169 return Double.parseDouble(magvar); 1170 } 1171 1172 /** 1173 * <pre> 1174 * name : GEOIDHEIGHT 1175 * attributes : 1176 * structure : double 1177 * </pre> 1178 * 1179 * @throws IOException 1180 * @throws XMLStreamException 1181 */ 1182 private double __geoidheight() throws IOException, XMLStreamException { 1183 String geoidheight; 1184 XMLEvent e; 1185 1186 e = getNextEvent(); 1187 checkValid(e, XMLEvent.START_ELEMENT, "geoidheight"); 1188 1189 geoidheight = __characters(); 1190 1191 e = getNextEvent(); 1192 checkValid(e, XMLEvent.END_ELEMENT, "geoidheight"); 1193 1194 return Double.parseDouble(geoidheight); 1195 } 1196 1197 /** 1198 * <pre> 1199 * name : CMT 1200 * attributes : 1201 * structure : string 1202 * </pre> 1203 * 1204 * @throws IOException 1205 * @throws XMLStreamException 1206 */ 1207 private String __cmt() throws IOException, XMLStreamException { 1208 String cmt; 1209 XMLEvent e; 1210 1211 e = getNextEvent(); 1212 checkValid(e, XMLEvent.START_ELEMENT, "cmt"); 1213 1214 cmt = __characters(); 1215 1216 e = getNextEvent(); 1217 checkValid(e, XMLEvent.END_ELEMENT, "cmt"); 1218 1219 return cmt; 1220 } 1221 1222 /** 1223 * <pre> 1224 * name : SRC 1225 * attributes : 1226 * structure : string 1227 * </pre> 1228 * 1229 * @throws IOException 1230 * @throws XMLStreamException 1231 */ 1232 private String __src() throws IOException, XMLStreamException { 1233 String src; 1234 XMLEvent e; 1235 1236 e = getNextEvent(); 1237 checkValid(e, XMLEvent.START_ELEMENT, "src"); 1238 1239 src = __characters(); 1240 1241 e = getNextEvent(); 1242 checkValid(e, XMLEvent.END_ELEMENT, "src"); 1243 1244 return src; 1245 } 1246 1247 /** 1248 * <pre> 1249 * name : SYM 1250 * attributes : 1251 * structure : string 1252 * </pre> 1253 * 1254 * @throws IOException 1255 * @throws XMLStreamException 1256 */ 1257 private String __sym() throws IOException, XMLStreamException { 1258 String sym; 1259 XMLEvent e; 1260 1261 e = getNextEvent(); 1262 checkValid(e, XMLEvent.START_ELEMENT, "sym"); 1263 1264 sym = __characters(); 1265 1266 e = getNextEvent(); 1267 checkValid(e, XMLEvent.END_ELEMENT, "sym"); 1268 1269 return sym; 1270 } 1271 1272 /** 1273 * <pre> 1274 * name : TEXT 1275 * attributes : 1276 * structure : string 1277 * </pre> 1278 * 1279 * @throws IOException 1280 * @throws XMLStreamException 1281 */ 1282 private String __text() throws IOException, XMLStreamException { 1283 String text; 1284 XMLEvent e; 1285 1286 e = getNextEvent(); 1287 checkValid(e, XMLEvent.START_ELEMENT, "text"); 1288 1289 text = __characters(); 1290 1291 e = getNextEvent(); 1292 checkValid(e, XMLEvent.END_ELEMENT, "text"); 1293 1294 return text; 1295 } 1296 1297 /** 1298 * <pre> 1299 * name : TYPE 1300 * attributes : 1301 * structure : string 1302 * </pre> 1303 * 1304 * @throws IOException 1305 * @throws XMLStreamException 1306 */ 1307 private String __type() throws IOException, XMLStreamException { 1308 String type; 1309 XMLEvent e; 1310 1311 e = getNextEvent(); 1312 checkValid(e, XMLEvent.START_ELEMENT, "type"); 1313 1314 type = __characters(); 1315 1316 e = getNextEvent(); 1317 checkValid(e, XMLEvent.END_ELEMENT, "type"); 1318 1319 return type; 1320 } 1321 1322 /** 1323 * <pre> 1324 * name : FIX 1325 * attributes : 1326 * structure : enum FixType 1327 * </pre> 1328 * 1329 * @throws IOException 1330 * @throws XMLStreamException 1331 */ 1332 private String __fix() throws IOException, XMLStreamException { 1333 String fix; 1334 XMLEvent e; 1335 1336 e = getNextEvent(); 1337 checkValid(e, XMLEvent.START_ELEMENT, "fix"); 1338 1339 fix = __characters(); 1340 1341 if (!fix.toLowerCase().matches("^(none|2d|3d|dgps|pps)$")) 1342 throw newParseError(e, 1343 "invalid fix type, expecting one of 'none', '2d', '3d', 'dgps', 'pps'"); 1344 1345 e = getNextEvent(); 1346 checkValid(e, XMLEvent.END_ELEMENT, "fix"); 1347 1348 return fix; 1349 } 1350 1351 /** 1352 * <pre> 1353 * name : SAT 1354 * attributes : 1355 * structure : positive integer 1356 * </pre> 1357 * 1358 * @throws IOException 1359 * @throws XMLStreamException 1360 */ 1361 private int __sat() throws IOException, XMLStreamException { 1362 String sat; 1363 XMLEvent e; 1364 1365 e = getNextEvent(); 1366 checkValid(e, XMLEvent.START_ELEMENT, "sat"); 1367 1368 sat = __characters(); 1369 1370 e = getNextEvent(); 1371 checkValid(e, XMLEvent.END_ELEMENT, "sat"); 1372 1373 return Integer.parseInt(sat); 1374 } 1375 1376 /** 1377 * <pre> 1378 * name : HDOP 1379 * attributes : 1380 * structure : double 1381 * </pre> 1382 * 1383 * @throws IOException 1384 * @throws XMLStreamException 1385 */ 1386 private double __hdop() throws IOException, XMLStreamException { 1387 String hdop; 1388 XMLEvent e; 1389 1390 e = getNextEvent(); 1391 checkValid(e, XMLEvent.START_ELEMENT, "hdop"); 1392 1393 hdop = __characters(); 1394 1395 e = getNextEvent(); 1396 checkValid(e, XMLEvent.END_ELEMENT, "hdop"); 1397 1398 return Double.parseDouble(hdop); 1399 } 1400 1401 /** 1402 * <pre> 1403 * name : VDOP 1404 * attributes : 1405 * structure : double 1406 * </pre> 1407 * 1408 * @throws IOException 1409 * @throws XMLStreamException 1410 */ 1411 private double __vdop() throws IOException, XMLStreamException { 1412 String vdop; 1413 XMLEvent e; 1414 1415 e = getNextEvent(); 1416 checkValid(e, XMLEvent.START_ELEMENT, "vdop"); 1417 1418 vdop = __characters(); 1419 1420 e = getNextEvent(); 1421 checkValid(e, XMLEvent.END_ELEMENT, "vdop"); 1422 1423 return Double.parseDouble(vdop); 1424 } 1425 1426 /** 1427 * <pre> 1428 * name : PDOP 1429 * attributes : 1430 * structure : double 1431 * </pre> 1432 * 1433 * @throws IOException 1434 * @throws XMLStreamException 1435 */ 1436 private double __pdop() throws IOException, XMLStreamException { 1437 String pdop; 1438 XMLEvent e; 1439 1440 e = getNextEvent(); 1441 checkValid(e, XMLEvent.START_ELEMENT, "pdop"); 1442 1443 pdop = __characters(); 1444 1445 e = getNextEvent(); 1446 checkValid(e, XMLEvent.END_ELEMENT, "pdop"); 1447 1448 return Double.parseDouble(pdop); 1449 } 1450 1451 /** 1452 * <pre> 1453 * name : AGEOFDGPSDATA 1454 * attributes : 1455 * structure : double 1456 * </pre> 1457 * 1458 * @throws IOException 1459 * @throws XMLStreamException 1460 */ 1461 private double __ageofdgpsdata() throws IOException, XMLStreamException { 1462 String ageofdgpsdata; 1463 XMLEvent e; 1464 1465 e = getNextEvent(); 1466 checkValid(e, XMLEvent.START_ELEMENT, "ageofdgpsdata"); 1467 1468 ageofdgpsdata = __characters(); 1469 1470 e = getNextEvent(); 1471 checkValid(e, XMLEvent.END_ELEMENT, "ageofdgpsdata"); 1472 1473 return Double.parseDouble(ageofdgpsdata); 1474 } 1475 1476 /** 1477 * <pre> 1478 * name : DGPSID 1479 * attributes : 1480 * structure : integer in [0,1023] 1481 * </pre> 1482 * 1483 * @throws IOException 1484 * @throws XMLStreamException 1485 */ 1486 private int __dgpsid() throws IOException, XMLStreamException { 1487 String dgpsid; 1488 XMLEvent e; 1489 1490 e = getNextEvent(); 1491 checkValid(e, XMLEvent.START_ELEMENT, "dgpsid"); 1492 1493 dgpsid = __characters(); 1494 1495 e = getNextEvent(); 1496 checkValid(e, XMLEvent.END_ELEMENT, "dgpsid"); 1497 1498 return Integer.parseInt(dgpsid); 1499 } 1500 1501 /** 1502 * <pre> 1503 * name : NUMBER 1504 * attributes : 1505 * structure : positive integer 1506 * </pre> 1507 * 1508 * @throws IOException 1509 * @throws XMLStreamException 1510 */ 1511 private int __number() throws IOException, XMLStreamException { 1512 String number; 1513 XMLEvent e; 1514 1515 e = getNextEvent(); 1516 checkValid(e, XMLEvent.START_ELEMENT, "number"); 1517 1518 number = __characters(); 1519 1520 e = getNextEvent(); 1521 checkValid(e, XMLEvent.END_ELEMENT, "number"); 1522 1523 return Integer.parseInt(number); 1524 } 1525 1526 /** 1527 * <pre> 1528 * name : RTEPT 1529 * attributes : 1530 * structure : __wptType 1531 * </pre> 1532 * 1533 * @throws IOException 1534 * @throws XMLStreamException 1535 */ 1536 private WayPoint __rtept() throws IOException, XMLStreamException { 1537 return waypoint("rtept"); 1538 } 1539 1540 /** 1541 * <pre> 1542 * name : TRKPT 1543 * attributes : 1544 * structure : __wptType 1545 * </pre> 1546 * 1547 * @throws IOException 1548 * @throws XMLStreamException 1549 */ 1550 private WayPoint __trkpt() throws IOException, XMLStreamException { 1551 return waypoint("trkpt"); 1552 } 1553 1554 /** 1555 * <pre> 1556 * name : TRKSEG 1557 * attributes : 1558 * structure : TRKPT* EXTENSIONS? 1559 * </pre> 1560 * 1561 * @throws IOException 1562 * @throws XMLStreamException 1563 */ 1564 private List<WayPoint> __trkseg() throws IOException, 1565 XMLStreamException { 1566 LinkedList<WayPoint> points = new LinkedList<WayPoint>(); 1567 XMLEvent e; 1568 1569 e = getNextEvent(); 1570 checkValid(e, XMLEvent.START_ELEMENT, "trkseg"); 1571 1572 e = getNextEvent(); 1573 1574 while (isEvent(e, XMLEvent.START_ELEMENT, "trkpt")) { 1575 pushback(e); 1576 points.addLast(__trkpt()); 1577 1578 e = getNextEvent(); 1579 } 1580 1581 if (isEvent(e, XMLEvent.START_ELEMENT, "extensions")) { 1582 pushback(e); 1583 __extensions(); 1584 1585 e = getNextEvent(); 1586 } 1587 1588 checkValid(e, XMLEvent.END_ELEMENT, "trkseg"); 1589 1590 return points; 1591 } 1592 1593 /** 1594 * <pre> 1595 * name : EMAIL 1596 * attributes : EMAILAttribute 1597 * structure : 1598 * </pre> 1599 * 1600 * @throws IOException 1601 * @throws XMLStreamException 1602 */ 1603 private String __email() throws IOException, XMLStreamException { 1604 XMLEvent e; 1605 EnumMap<EMAILAttribute, String> attributes; 1606 String email = ""; 1607 1608 e = getNextEvent(); 1609 checkValid(e, XMLEvent.START_ELEMENT, "email"); 1610 1611 attributes = getAttributes(EMAILAttribute.class, e.asStartElement()); 1612 1613 if (!attributes.containsKey(EMAILAttribute.ID)) { 1614 XMLStreamException ex = newParseError(e, 1615 "attribute 'version' is required"); 1616 1617 if (strict) 1618 throw ex; 1619 else 1620 ex.printStackTrace(); 1621 } else 1622 email += attributes.get(EMAILAttribute.ID); 1623 1624 email += "@"; 1625 1626 if (!attributes.containsKey(EMAILAttribute.DOMAIN)) { 1627 XMLStreamException ex = newParseError(e, 1628 "attribute 'version' is required"); 1629 1630 if (strict) 1631 throw ex; 1632 else 1633 ex.printStackTrace(); 1634 } else 1635 email += attributes.get(EMAILAttribute.DOMAIN); 1636 1637 e = getNextEvent(); 1638 checkValid(e, XMLEvent.END_ELEMENT, "email"); 1639 1640 return email; 1641 } 1642 1643 /** 1644 * <pre> 1645 * name : YEAR 1646 * attributes : 1647 * structure : string 1648 * </pre> 1649 * 1650 * @throws IOException 1651 * @throws XMLStreamException 1652 */ 1653 private String __year() throws IOException, XMLStreamException { 1654 String year; 1655 XMLEvent e; 1656 1657 e = getNextEvent(); 1658 checkValid(e, XMLEvent.START_ELEMENT, "year"); 1659 1660 year = __characters(); 1661 1662 e = getNextEvent(); 1663 checkValid(e, XMLEvent.END_ELEMENT, "year"); 1664 1665 return year; 1666 } 1667 1668 /** 1669 * <pre> 1670 * name : LICENSE 1671 * attributes : 1672 * structure : string 1673 * </pre> 1674 * 1675 * @throws IOException 1676 * @throws XMLStreamException 1677 */ 1678 private String __license() throws IOException, XMLStreamException { 1679 String license; 1680 XMLEvent e; 1681 1682 e = getNextEvent(); 1683 checkValid(e, XMLEvent.START_ELEMENT, "license"); 1684 1685 license = __characters(); 1686 1687 e = getNextEvent(); 1688 checkValid(e, XMLEvent.END_ELEMENT, "license"); 1689 1690 return license; 1691 } 1692 } 1693 1694 public static interface GPXConstants { 1695 public static enum Balise { 1696 GPX, METADATA, WPT, RTE, TRK, EXTENSIONS, NAME, DESC, AUTHOR, COPYRIGHT, LINK, TIME, KEYWORDS, BOUNDS, ELE, MAGVAR, GEOIDHEIGHT, CMT, SRC, SYM, TYPE, FIX, SAT, HDOP, VDOP, PDOP, AGEOFDGPSDATA, DGPSID, NUMBER, RTEPT, TRKSEG, TRKPT, YEAR, LICENCE, TEXT, EMAIL, PT 1697 } 1698 1699 public static enum GPXAttribute { 1700 CREATOR, VERSION 1701 } 1702 1703 public static enum WPTAttribute { 1704 LAT, LON 1705 } 1706 1707 public static enum LINKAttribute { 1708 HREF 1709 } 1710 1711 public static enum EMAILAttribute { 1712 ID, DOMAIN 1713 } 1714 1715 public static enum PTAttribute { 1716 LAT, LON 1717 } 1718 1719 public static enum BOUNDSAttribute { 1720 MINLAT, MAXLAT, MINLON, MAXLON 1721 } 1722 1723 public static enum COPYRIGHTAttribute { 1724 AUTHOR 1725 } 1726 1727 public static enum FixType { 1728 T_NONE, T_2D, T_3D, T_DGPS, T_PPS 1729 } 1730 } 1731}