package org.commcare.logging;
import org.commcare.AppUtils;
import org.commcare.CommCareApplication;
import org.commcare.android.javarosa.DeviceReportRecord;
import org.commcare.models.database.SqlStorage;
import org.javarosa.core.model.User;
import org.javarosa.core.model.utils.DateUtils;
import org.kxml2.io.KXmlSerializer;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
/**
* This class generates and serializes a device report to either a byte array
* or to a file as designated by a log record
*
* @author ctsims
*/
public class DeviceReportWriter {
public static final String XMLNS = "http://code.javarosa.org/devicereport";
private final XmlSerializer serializer;
private final OutputStream os;
private final ArrayList<DeviceReportElement> elements = new ArrayList<>();
public DeviceReportWriter(DeviceReportRecord record) throws IOException {
this(record.openOutputStream());
}
public DeviceReportWriter(OutputStream outputStream) throws IOException {
os = outputStream;
serializer = new KXmlSerializer();
serializer.setOutput(os, "UTF-8");
serializer.setPrefix("", XMLNS);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
}
public void addReportElement(DeviceReportElement element) {
this.elements.add(element);
}
public void write() throws IllegalArgumentException, IllegalStateException, IOException {
try {
serializer.startDocument("UTF-8", null);
serializer.startTag(XMLNS, "device_report");
try {
//All inner elements are supposed to catch their errors and wrap them, so we
//can safely catch any of the processing issues
try {
writeHeader();
} catch (Exception e) {
}
try {
writeUserReport();
} catch (Exception e) {
}
for (DeviceReportElement element : elements) {
try {
element.writeToDeviceReport(serializer);
} catch (Exception e) {
}
}
} finally {
serializer.endTag(XMLNS, "device_report");
}
serializer.endDocument();
} finally {
try {
os.close();
} catch (IOException e) {
}
}
}
private void writeHeader() throws IllegalArgumentException, IllegalStateException, IOException {
CommCareApplication application = CommCareApplication.instance();
String did = application.getPhoneId();
writeText("device_id", did);
writeText("report_date", DateUtils.formatDateTime(new Date(), DateUtils.FORMAT_ISO8601));
writeText("app_version", AppUtils.getCurrentVersionString());
}
private void writeUserReport() throws IllegalArgumentException, IllegalStateException, IOException {
SqlStorage<User> storage = CommCareApplication.instance().getUserStorage(User.STORAGE_KEY, User.class);
serializer.startTag(XMLNS, "user_subreport");
try {
for (User u : storage) {
writeUser(u);
}
} finally {
serializer.endTag(XMLNS, "user_subreport");
}
}
private void writeUser(User user) throws IllegalArgumentException, IllegalStateException, IOException {
serializer.startTag(XMLNS, "user");
try {
writeText("username", user.getUsername());
writeText("user_id", user.getUniqueId());
writeText("sync_token", user.getLastSyncToken());
} finally {
serializer.endTag(XMLNS, "user");
}
}
private void writeText(String element, String text) throws IllegalArgumentException, IllegalStateException, IOException {
serializer.startTag(XMLNS, element);
try {
serializer.text(text);
} catch (Exception e) {
e.printStackTrace();
} finally {
serializer.endTag(XMLNS, element);
}
}
}