diff --git a/MyTracks/res/values/strings.xml b/MyTracks/res/values/strings.xml index 640a700e2..3ec314cbf 100644 --- a/MyTracks/res/values/strings.xml +++ b/MyTracks/res/values/strings.xml @@ -559,6 +559,22 @@ limitations under the License. %1$s time. E.g, '2/15/2012 1:40 PM'"> Recorded: %1$s + + Battery level (%) + + + Cadence (rpm) + + + Heart rate (bpm) + + + Power (W) + powerList = new ArrayList(); + private ArrayList cadenceList = new ArrayList(); + private ArrayList heartRateList = new ArrayList(); + private ArrayList batteryLevelList = new ArrayList(); + private boolean hasPower; + private boolean hasCadence; + private boolean hasHeartRate; + private boolean hasBatteryLevel; + public KmlTrackWriter(Context context) { - descriptionGenerator = new DescriptionGeneratorImpl(context); + this(context, new DescriptionGeneratorImpl(context)); } @VisibleForTesting - KmlTrackWriter(DescriptionGenerator descriptionGenerator) { + KmlTrackWriter(Context context, DescriptionGenerator descriptionGenerator) { + this.context = context; this.descriptionGenerator = descriptionGenerator; } - @SuppressWarnings("hiding") - @Override - public void prepare(Track track, OutputStream out) { - this.track = track; - this.pw = new PrintWriter(out); - } - @Override public String getExtension() { return TrackFileFormat.KML.getExtension(); } @Override - public void writeHeader() { - if (pw != null) { - pw.println(""); - pw.print(""); - pw.println(""); - pw.format("My Tracks running on %s" - + "\n", Build.MODEL); + public void prepare(Track aTrack, OutputStream outputStream) { + this.track = aTrack; + this.printWriter = new PrintWriter(outputStream); + } - pw.println("" + StringUtils.stringAsCData(track.getName()) - + ""); - pw.println("" - + StringUtils.stringAsCData(track.getDescription()) - + ""); - writeStyles(); + @Override + public void close() { + if (printWriter != null) { + printWriter.close(); + printWriter = null; + } + } + + @Override + public void writeHeader() { + if (printWriter != null) { + printWriter.println(""); + printWriter.println(""); + printWriter.println(""); + printWriter.println("1"); + printWriter.println("1"); + printWriter.println( + "" + StringUtils.stringAsCData(track.getDescription()) + ""); + printWriter.println("" + StringUtils.stringAsCData(track.getName()) + ""); + printWriter.println("" + StringUtils.stringAsCData( + context.getString(R.string.send_google_by_my_tracks, "", "")) + + ""); + writeTrackStyle(); + writePlacemarkerStyle( + START_STYLE, "http://maps.google.com/mapfiles/kml/paddle/grn-circle.png", 32, 1); + writePlacemarkerStyle( + END_STYLE, "http://maps.google.com/mapfiles/kml/paddle/red-circle.png", 32, 1); + writePlacemarkerStyle( + STATISTICS_STYLE, "http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png", 20, 2); + writePlacemarkerStyle( + WAYPOINT_STYLE, "http://maps.google.com/mapfiles/kml/pushpin/blue-pushpin.png", 20, 2); + printWriter.println(""); + writeSensorStyle(POWER, context.getString(R.string.description_sensor_power)); + writeSensorStyle(CADENCE, context.getString(R.string.description_sensor_cadence)); + writeSensorStyle(HEART_RATE, context.getString(R.string.description_sensor_heart_rate)); + writeSensorStyle(BATTER_LEVEL, context.getString(R.string.description_sensor_battery_level)); + printWriter.println(""); } } @Override public void writeFooter() { - if (pw != null) { - pw.println(""); - pw.println(""); + if (printWriter != null) { + printWriter.println(""); + printWriter.println(""); } } @Override - public void writeBeginTrack(Location firstPoint) { - if (pw != null) { - writePlacemark("(Start)", track.getDescription(), "#sh_green-circle", - firstPoint); - pw.println(""); - pw.println("" + StringUtils.stringAsCData(track.getName()) - + ""); - pw.println("" - + StringUtils.stringAsCData(track.getDescription()) - + ""); - pw.println("#track"); - pw.println(""); + public void writeBeginWaypoints() { + if (printWriter != null) { + printWriter.println( + "" + StringUtils.stringAsCData(context.getString(R.string.menu_markers)) + + ""); } } @Override - public void writeEndTrack(Location lastPoint) { - if (pw != null) { - pw.println(""); - pw.println(""); - String description = descriptionGenerator.generateTrackDescription( - track, distances, elevations); - writePlacemark("(End)", description, "#sh_red-circle", lastPoint); + public void writeEndWaypoints() { + if (printWriter != null) { + printWriter.println(""); + } + } + + @Override + public void writeWaypoint(Waypoint waypoint) { + if (printWriter != null) { + String styleName = waypoint.getType() == Waypoint.TYPE_STATISTICS ? STATISTICS_STYLE + : WAYPOINT_STYLE; + writePlacemark( + waypoint.getName(), waypoint.getDescription(), styleName, waypoint.getLocation()); + } + } + + @Override + public void writeBeginTrack(Location firstLocation) { + if (printWriter != null) { + String name = context.getString(R.string.marker_label_start, track.getName()); + writePlacemark(name, track.getDescription(), START_STYLE, firstLocation); + printWriter.println(""); + printWriter.println( + "" + StringUtils.stringAsCData(track.getDescription()) + ""); + printWriter.println("" + StringUtils.stringAsCData(track.getName()) + ""); + printWriter.println("#" + TRACK_STYLE + ""); + printWriter.println(""); + printWriter.println("absolute"); + printWriter.println("1"); + } + } + + @Override + public void writeEndTrack(Location lastLocation) { + if (printWriter != null) { + printWriter.println(""); + printWriter.println(""); + String name = context.getString(R.string.marker_label_end, track.getName()); + String description = descriptionGenerator.generateTrackDescription(track, null, null); + writePlacemark(name, description, END_STYLE, lastLocation); } } @Override public void writeOpenSegment() { - if (pw != null) { - pw.print(""); + if (printWriter != null) { + printWriter.println(""); + hasPower = false; + hasCadence = false; + hasHeartRate = false; + hasBatteryLevel = false; + powerList.clear(); + cadenceList.clear(); + heartRateList.clear(); + batteryLevelList.clear(); } } @Override public void writeCloseSegment() { - if (pw != null) { - pw.println(""); + if (printWriter != null) { + printWriter.println(""); + printWriter.println(""); + if (hasPower) { + writeSensorData(powerList, POWER); + } + if (hasCadence) { + writeSensorData(cadenceList, CADENCE); + } + if (hasHeartRate) { + writeSensorData(heartRateList, HEART_RATE); + } + if (hasBatteryLevel) { + writeSensorData(batteryLevelList, BATTER_LEVEL); + } + printWriter.println(""); + printWriter.println(""); + printWriter.println(""); } } @Override - public void writeLocation(Location l) { - if (pw != null) { - pw.print(l.getLongitude() + "," + l.getLatitude() + "," - + l.getAltitude() + " "); + public void writeLocation(Location location) { + if (printWriter != null) { + printWriter.println("" + StringUtils.formatXmlDateTime(location.getTime()) + ""); + printWriter.println( + "" + location.getLongitude() + " " + location.getLatitude() + " " + + location.getAltitude() + ""); + if (location instanceof MyTracksLocation) { + SensorDataSet sensorDataSet = ((MyTracksLocation) location).getSensorDataSet(); + int power = -1; + int cadence = -1; + int heartRate = -1; + int batteryLevel = -1; + + if (sensorDataSet != null) { + if (sensorDataSet.hasPower()) { + SensorData sensorData = sensorDataSet.getPower(); + if (sensorData.hasValue() && sensorData.getState() == Sensor.SensorState.SENDING) { + hasPower = true; + power = sensorData.getValue(); + } + } + if (sensorDataSet.hasCadence()) { + SensorData sensorData = sensorDataSet.getCadence(); + if (sensorData.hasValue() && sensorData.getState() == Sensor.SensorState.SENDING) { + hasCadence = true; + cadence = sensorData.getValue(); + } + } + if (sensorDataSet.hasHeartRate()) { + SensorData sensorData = sensorDataSet.getHeartRate(); + if (sensorData.hasValue() && sensorData.getState() == Sensor.SensorState.SENDING) { + hasHeartRate = true; + heartRate = sensorData.getValue(); + } + } + if (sensorDataSet.hasBatteryLevel()) { + SensorData sensorData = sensorDataSet.getBatteryLevel(); + if (sensorData.hasValue() && sensorData.getState() == Sensor.SensorState.SENDING) { + hasBatteryLevel = true; + batteryLevel = sensorData.getValue(); + } + } + } + powerList.add(power); + cadenceList.add(cadence); + heartRateList.add(heartRate); + batteryLevelList.add(batteryLevel); + } } } - private String getPinStyle(Waypoint waypoint) { - if (waypoint.getType() == Waypoint.TYPE_STATISTICS) { - return "#sh_ylw-pushpin"; + /** + * Writes the sensor data. + * + * @param list a list of sensor data + * @param name the name of the sensor data + */ + private void writeSensorData(ArrayList list, String name) { + printWriter.println(""); + for (int i = 0; i < list.size(); i++) { + printWriter.println("" + list.get(i) + ""); } - // Try to find the icon color. - // The string should be of the form: - // "http://maps.google.com/mapfiles/ms/micons/XXX.png" - int slash = waypoint.getIcon().lastIndexOf('/'); - int png = waypoint.getIcon().lastIndexOf('.'); - if ((slash != -1) && (slash < png)) { - String color = waypoint.getIcon().substring(slash + 1, png); - return "#sh_" + color + "-pushpin"; - } - return "#sh_blue-pushpin"; + printWriter.println(""); } - @Override - public void writeWaypoint(Waypoint waypoint) { - if (pw != null) { - writePlacemark( - waypoint.getName(), - waypoint.getDescription(), - getPinStyle(waypoint), - waypoint.getLocation()); - } - } - - @Override - public void close() { - if (pw != null) { - pw.close(); - pw = null; - } - } - - private void writeStyles() { - pw.println(""); - - pw.print(""); - - pw.print(""); - - pw.print(""); - - pw.print(""); - - pw.print(""); - - pw.print(""); - } - - private void writePlacemark(String name, String description, String style, - Location location) { + /** + * Writes a placemark. + * + * @param name the name of the placemark + * @param description the description + * @param styleName the style name + * @param location the location + */ + private void writePlacemark( + String name, String description, String styleName, Location location) { if (location != null) { - pw.println(""); - pw.println(" " + StringUtils.stringAsCData(name) + ""); - pw.println(" " + StringUtils.stringAsCData(description) - + ""); - pw.println(" " + style + ""); - pw.println(" "); - pw.println(" " + location.getLongitude() + "," - + location.getLatitude() + ""); - pw.println(" "); - pw.println(""); + printWriter.println(""); + printWriter.println( + "" + StringUtils.stringAsCData(description) + ""); + printWriter.println("" + StringUtils.stringAsCData(name) + ""); + printWriter.println("#" + styleName + ""); + printWriter.println(""); + printWriter.println( + "" + location.getLongitude() + "," + location.getLatitude() + "," + + location.getAltitude() + ""); + printWriter.println(""); + printWriter.println(""); } } + + /** + * Writes the track style. + */ + private void writeTrackStyle() { + printWriter.println(""); + } + + /** + * Writes a placemarker style. + * + * @param name the name of the style + * @param url the url of the style icon + * @param x the x position of the hotspot + * @param y the y position of the hotspot + */ + private void writePlacemarkerStyle(String name, String url, int x, int y) { + printWriter.println(""); + } + + /** + * Writes a sensor style. + * + * @param name the name of the sesnor + * @param displayName the sensor display name + */ + private void writeSensorStyle(String name, String displayName) { + printWriter.println(""); + printWriter.println( + "" + StringUtils.stringAsCData(displayName) + ""); + printWriter.println(""); + } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/TcxTrackWriter.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/TcxTrackWriter.java index 9a76ed653..7085a8f79 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/TcxTrackWriter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/TcxTrackWriter.java @@ -291,6 +291,16 @@ public class TcxTrackWriter implements TrackFormatWriter { pw.println(""); } + @Override + public void writeBeginWaypoints() { + // Do nothing + } + + @Override + public void writeEndWaypoints() { + // Do nothing + } + @Override public void writeWaypoint(Waypoint waypoint) { // TODO Write out the waypoints somewhere. diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackFormatWriter.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackFormatWriter.java index 0b7101c6f..5766eee7c 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackFormatWriter.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackFormatWriter.java @@ -23,12 +23,15 @@ import android.location.Location; import java.io.OutputStream; /** - * Interface for writing data to a specific track file format. + * Interface for writing a track data to a specific file format. * * The expected sequence of calls is: *
    *
  1. {@link #prepare} *
  2. {@link #writeHeader} + *
  3. {@link #writeBeginWaypoints} + *
  4. For each waypoint: {@link #writeWaypoint} + *
  5. {@link #writeEndWaypoints} *
  6. {@link #writeBeginTrack} *
  7. For each segment: *
      @@ -37,8 +40,8 @@ import java.io.OutputStream; *
    1. {@link #writeCloseSegment} *
    *
  8. {@link #writeEndTrack} - *
  9. For each waypoint: {@link #writeWaypoint} *
  10. {@link #writeFooter} + *
  11. {@link #close} *
* * @author Rodrigo Damazio @@ -46,68 +49,78 @@ import java.io.OutputStream; public interface TrackFormatWriter { /** - * Sets up the writer to write the given track to the given output. - * - * @param track the track to write - * @param out the stream to write the track contents to + * Gets the file extension (i.e. gpx, kml, ...) */ - void prepare(Track track, OutputStream out); + public String getExtension(); /** - * @return The file extension (i.e. gpx, kml, ...) + * Sets up the writer to write the given track. + * + * @param track the track to write + * @param outputStream the output stream to write the track to */ - String getExtension(); + public void prepare(Track track, OutputStream outputStream); + + /** + * Closes the underlying file handler. + */ + public void close(); /** * Writes the header. - * This is chance for classes to write out opening information. */ - void writeHeader(); + public void writeHeader(); /** * Writes the footer. - * This is chance for classes to write out closing information. */ - void writeFooter(); + public void writeFooter(); /** - * Write the given location object. + * Writes the beginning of the waypoints. + */ + public void writeBeginWaypoints(); + + /** + * Writes the end of the waypoints. + */ + public void writeEndWaypoints(); + + /** + * Writes a waypoint. * - * TODO Add some flexible handling of other sensor data. + * @param waypoint the waypoint + */ + public void writeWaypoint(Waypoint waypoint); + + /** + * Writes the beginning of the track. + * + * @param firstLocation the first location + */ + public void writeBeginTrack(Location firstLocation); + + /** + * Writes the end of the track. + * + * @param lastLocation the last location + */ + public void writeEndTrack(Location lastLocation); + + /** + * Writes the statements necessary to open a new segment. + */ + public void writeOpenSegment(); + + /** + * Writes the statements necessary to close a segment. + */ + public void writeCloseSegment(); + + /** + * Writes a location. * - * @param location the location to write + * @param location the location */ - void writeLocation(Location location) throws InterruptedException; - - /** - * Write a way point. - * - * @param waypoint - */ - void writeWaypoint(Waypoint waypoint); - - /** - * Write the beginning of a track. - */ - void writeBeginTrack(Location firstPoint); - - /** - * Write the end of a track. - */ - void writeEndTrack(Location lastPoint); - - /** - * Write the statements necessary to open a new segment. - */ - void writeOpenSegment(); - - /** - * Write the statements necessary to close a segment. - */ - void writeCloseSegment(); - - /** - * Close the underlying file handle. - */ - void close(); -} + public void writeLocation(Location location); +} \ No newline at end of file diff --git a/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriterImpl.java b/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriterImpl.java index 51852802c..21617daa3 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriterImpl.java +++ b/MyTracks/src/com/google/android/apps/mytracks/io/file/TrackWriterImpl.java @@ -269,12 +269,17 @@ class TrackWriterImpl implements TrackWriter { Cursor cursor = null; cursor = providerUtils.getWaypointsCursor(trackId, 0, Constants.MAX_LOADED_WAYPOINTS_POINTS); + boolean hasWaypoints = false; if (cursor != null) { try { if (cursor.moveToFirst()) { // Yes, this will skip the 1st way point and that is intentional // as the 1st points holds the stats for the current/last segment. while (cursor.moveToNext()) { + if (!hasWaypoints) { + writer.writeBeginWaypoints(); + hasWaypoints = true; + } Waypoint wpt = providerUtils.createWaypoint(cursor); writer.writeWaypoint(wpt); } @@ -283,6 +288,9 @@ class TrackWriterImpl implements TrackWriter { cursor.close(); } } + if (hasWaypoints) { + writer.writeEndWaypoints(); + } } /** diff --git a/MyTracks/src/com/google/android/apps/mytracks/util/StringUtils.java b/MyTracks/src/com/google/android/apps/mytracks/util/StringUtils.java index 947ed062e..61efffe2d 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/util/StringUtils.java +++ b/MyTracks/src/com/google/android/apps/mytracks/util/StringUtils.java @@ -143,6 +143,16 @@ public class StringUtils { static { BASE_XML_DATE_FORMAT.setTimeZone(new SimpleTimeZone(0, "UTC")); } + + /** + * Formats the time to the XML date time format. + * + * @param time time in milliseconds + */ + public static final String formatXmlDateTime(long time) { + return BASE_XML_DATE_FORMAT.format(new Date(time)); + } + private static final Pattern XML_DATE_EXTRAS_PATTERN = Pattern.compile("^(\\.\\d+)?(?:Z|([+-])(\\d{2}):(\\d{2}))?$"); diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/KmlTrackWriterTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/KmlTrackWriterTest.java index 8072bf88d..93a6e2804 100644 --- a/MyTracksTest/src/com/google/android/apps/mytracks/io/file/KmlTrackWriterTest.java +++ b/MyTracksTest/src/com/google/android/apps/mytracks/io/file/KmlTrackWriterTest.java @@ -1,4 +1,19 @@ -// Copyright 2010 Google Inc. All Rights Reserved. +/* + * Copyright 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + package com.google.android.apps.mytracks.io.file; import com.google.android.apps.mytracks.content.DescriptionGenerator; @@ -14,7 +29,7 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; /** - * Tests for the KML track exporter. + * Tests for {@link KmlTrackWriter}. * * @author Rodrigo Damazio */ @@ -25,13 +40,10 @@ public class KmlTrackWriterTest extends TrackFormatWriterTest { * A fake version of {@link DescriptionGenerator} which returns a fixed track * description, thus not depending on the context. */ - private class MockDescriptionGenerator implements DescriptionGenerator { + private class FakeDescriptionGenerator implements DescriptionGenerator { @Override public String generateTrackDescription( - Track trackToDescribe, Vector distances, Vector elevations) { - assertSame(KmlTrackWriterTest.super.track, trackToDescribe); - assertTrue(distances.isEmpty()); - assertTrue(elevations.isEmpty()); + Track aTrack, Vector distances, Vector elevations) { return FULL_TRACK_DESCRIPTION; } @@ -42,7 +54,7 @@ public class KmlTrackWriterTest extends TrackFormatWriterTest { } public void testXmlOutput() throws Exception { - KmlTrackWriter writer = new KmlTrackWriter(new MockDescriptionGenerator()); + KmlTrackWriter writer = new KmlTrackWriter(getContext(), new FakeDescriptionGenerator()); String result = writeTrack(writer); Document doc = parseXmlDocument(result); @@ -51,65 +63,58 @@ public class KmlTrackWriterTest extends TrackFormatWriterTest { assertEquals(TRACK_NAME, getChildTextValue(docTag, "name")); assertEquals(TRACK_DESCRIPTION, getChildTextValue(docTag, "description")); - // There are 5 placemarks - start, segments, end, waypoint 1, waypoint 2 + // There are 5 placemarks - start, segments, end, waypoint1, waypoint2 List placemarkTags = getChildElements(docTag, "Placemark", 5); - assertTagIsPlacemark(placemarkTags.get(0), - "(Start)", TRACK_DESCRIPTION, location1); - assertTagIsPlacemark(placemarkTags.get(2), - "(End)", FULL_TRACK_DESCRIPTION, location4); - assertTagIsPlacemark(placemarkTags.get(3), - WAYPOINT1_NAME, WAYPOINT1_DESCRIPTION, location2); - assertTagIsPlacemark(placemarkTags.get(4), - WAYPOINT2_NAME, WAYPOINT2_DESCRIPTION, location3); + assertTagIsPlacemark( + placemarkTags.get(0), TRACK_NAME + " (Start)", TRACK_DESCRIPTION, location1); + assertTagIsPlacemark( + placemarkTags.get(2), TRACK_NAME + " (End)", FULL_TRACK_DESCRIPTION, location4); + assertTagIsPlacemark(placemarkTags.get(3), WAYPOINT1_NAME, WAYPOINT1_DESCRIPTION, location2); + assertTagIsPlacemark(placemarkTags.get(4), WAYPOINT2_NAME, WAYPOINT2_DESCRIPTION, location3); Element trackPlacemarkTag = placemarkTags.get(1); assertEquals(TRACK_NAME, getChildTextValue(trackPlacemarkTag, "name")); - assertEquals(TRACK_DESCRIPTION, - getChildTextValue(trackPlacemarkTag, "description")); - Element geometryTag = getChildElement(trackPlacemarkTag, "MultiGeometry"); - List segmentTags = getChildElements(geometryTag, "LineString", 2); - assertTagHasPoints(segmentTags.get(0), location1, location2); - assertTagHasPoints(segmentTags.get(1), location3, location4); + assertEquals(TRACK_DESCRIPTION, getChildTextValue(trackPlacemarkTag, "description")); + Element multiTrackTag = getChildElement(trackPlacemarkTag, "gx:MultiTrack"); + List trackTags = getChildElements(multiTrackTag, "gx:Track", 2); + assertTagHasPoints(trackTags.get(0), location1, location2); + assertTagHasPoints(trackTags.get(1), location3, location4); } /** - * Asserts that the given XML tag is a placemark with the given properties. + * Asserts that the given tag is a placemark with the given properties. * - * @param tag the tag to analyze - * @param name the expected name for the placemark - * @param description the expected description for the placemark - * @param location the expected location of the placemark + * @param tag the tag + * @param name the expected placemark name + * @param description the expected placemark description + * @param location the expected placemark location */ - private void assertTagIsPlacemark(Element tag, String name, - String description, Location location) { + private void assertTagIsPlacemark( + Element tag, String name, String description, Location location) { assertEquals(name, getChildTextValue(tag, "name")); assertEquals(description, getChildTextValue(tag, "description")); Element pointTag = getChildElement(tag, "Point"); - String expectedCoords = - location.getLongitude() + "," + location.getLatitude(); - String actualCoords = getChildTextValue(pointTag, "coordinates"); - assertEquals(expectedCoords, actualCoords); + String expected = location.getLongitude() + "," + location.getLatitude() + "," + + location.getAltitude(); + String actual = getChildTextValue(pointTag, "coordinates"); + assertEquals(expected, actual); } /** - * Asserts that the given tag has a "coordinates" subtag with the given - * locations. + * Asserts that the given tag has a list of "gx:coord" subtags matching the + * expected locations. * - * @param tag the tag to analyze - * @param locs the locations to expect in the coordinates + * @param tag the parent tag + * @param locations list of expected locations */ - private void assertTagHasPoints(Element tag, Location... locs) { - StringBuilder expectedBuilder = new StringBuilder(); - for (Location loc : locs) { - expectedBuilder.append(loc.getLongitude()); - expectedBuilder.append(','); - expectedBuilder.append(loc.getLatitude()); - expectedBuilder.append(','); - expectedBuilder.append(loc.getAltitude()); - expectedBuilder.append(' '); + private void assertTagHasPoints(Element tag, Location... locations) { + List coordTags = getChildElements(tag, "gx:coord", locations.length); + for (int i = 0; i < locations.length; i++) { + Location location = locations[i]; + String expected = location.getLongitude() + " " + location.getLatitude() + " " + + location.getAltitude(); + String actual = coordTags.get(i).getFirstChild().getTextContent(); + assertEquals(expected, actual); } - String expectedCoordinates = expectedBuilder.toString().trim(); - String actualCoordinates = getChildTextValue(tag, "coordinates").trim(); - assertEquals(expectedCoordinates, actualCoordinates); } }