/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.mozstumbler.client.serialize;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Build;
import android.util.Log;
import org.mozilla.mozstumbler.BuildConfig;
import org.mozilla.mozstumbler.client.mapview.ObservationPoint;
import org.mozilla.mozstumbler.service.AppGlobals;
import org.mozilla.mozstumbler.svclocator.services.log.LoggerUtil;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Namespace;
import org.simpleframework.xml.NamespaceList;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import java.io.File;
import java.lang.ref.WeakReference;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.TimeZone;
public class GpxObservationPointSerializer extends AsyncTask<Void, Void, Boolean> {
private static final String LOG_TAG = LoggerUtil.makeLogTag(GpxObservationPointSerializer.class);
final WeakReference<IListener> mObservationPointSerializerListener;
private final LinkedList<ObservationPoint> mPointList;
private File mFile;
GpxObservationPointSerializer(IListener listener, File file,
LinkedList<ObservationPoint> pointList) {
mObservationPointSerializerListener = new WeakReference<IListener>(listener);
mFile = file;
mPointList = pointList;
}
synchronized boolean writeOut(File outFile) {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
Gpx gpx = new Gpx();
gpx.creator = "Mozilla Stumbler " + BuildConfig.VERSION_NAME;
if (AppGlobals.isDebug) {
gpx.creator += " (" + BuildConfig.GIT_DESCRIPTION + ")";
}
Trk trk = new Trk();
gpx.trk.add(trk);
Trkseg seg;
for (ObservationPoint observationPoint : mPointList) {
if (observationPoint.mTrackSegment < 0) {
continue;
}
while (trk.trkseg.size() <= observationPoint.mTrackSegment) {
trk.trkseg.add(new Trkseg());
}
seg = trk.trkseg.get(observationPoint.mTrackSegment);
Location loc = observationPoint.pointGPS;
Trkpt pt = new Trkpt();
pt.lat = loc.getLatitude();
pt.lon = loc.getLongitude();
pt.time = df.format(new Date(loc.getTime()));
if (loc.hasAltitude()) {
pt.geoidheight = loc.getAltitude();
}
if (loc.hasAccuracy()) {
pt.pdop = loc.getAccuracy();
}
seg.trkpt.add(pt);
}
Serializer gpxSerializer = new Persister();
try {
gpxSerializer.write(gpx, outFile);
} catch (Exception e) {
Log.e(LOG_TAG, e.getMessage());
return false;
}
Log.d(LOG_TAG, "write done");
return true;
}
@Override
protected Boolean doInBackground(Void... params) {
return writeOut(mFile);
}
@Override
protected void onPostExecute(Boolean result) {
IListener listener = mObservationPointSerializerListener.get();
if (listener == null) {
return;
}
if (!result) {
listener.onError();
return;
}
listener.onWriteComplete(mFile);
}
public interface IListener {
void onWriteComplete(File file);
void onError();
}
@Root
@NamespaceList({
@Namespace(reference="http://www.topografix.com/GPX/1/1"),
@Namespace(reference="http://www.w3.org/2001/XMLSchema-instance", prefix="xsi")
})
static class Gpx {
// TODO optional: time, bounds, author
@Attribute
static final String version = "1.1";
@Attribute
static final String schemaLocation = "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd";
@Attribute
String creator;
@ElementList(inline=true)
List<Trk> trk;
Gpx() {
trk = new LinkedList<Trk>();
}
}
@Root
static class Trk {
@Element
static final String src = Build.MANUFACTURER + " " + Build.MODEL + " (" + Build.HARDWARE + ")";
@ElementList(inline=true)
List<Trkseg> trkseg;
Trk() {
trkseg = new LinkedList<Trkseg>();
}
}
@Root
static class Trkseg {
@ElementList(inline=true)
List<Trkpt> trkpt;
Trkseg() {
trkpt = new LinkedList<Trkpt>();
}
}
@Root
static class Trkpt {
@Attribute
double lat;
@Attribute
double lon;
@Element
String time;
@Element(required=false)
Double geoidheight;
@Element(required=false)
Float pdop;
}
}