@@ -0,0 +1,3345 @@
+package org.wikipedia.eventlogging;%0A%0Aimport android.net.*;%0Aimport android.util.*;%0Aimport com.github.kevinsawicki.http.*;%0Aimport org.json.*;%0Aimport org.wikipedia.concurrency.*;%0A%0A/**%0A * Base class for all various types of events that are logged to EventLogging.%0A *%0A * Each Schema has its own class, and has its own constructor that makes it easy%0A * to call from everywhere without having to duplicate param info at all places.%0A * Updating schemas / revisions is also easier this way.%0A */%0Apublic abstract class EventLoggingEvent %7B%0A    private static final String EVENTLOG_URL = %22https://bits.wikimedia.org/event.gif%22;%0A%0A    private final JSONObject data;%0A%0A    /**%0A     * Create an EventLoggingEvent that logs to a given revision of a given schema with%0A     * the gven data payload.%0A     *%0A     * @param schema Schema name (as specified on meta.wikimedia.org)%0A     * @param revID Revision of the schema to log to%0A     * @param payload Data for the actual event payload. Considered to be%0A     *                an array of alternating key and value items (for easier%0A     *                construction in subclass constructors).%0A     *%0A     *                For example, what would be expressed in a more sane%0A     *                language as:%0A     *%0A     *                new SomeSubClass(%22Schema%22, 4200, %7B%0A     *                  %22page%22: %22List of mass murderers%22,%0A     *                  %22section%22: %222014%22%0A     *                %7D);%0A     *%0A     *                would be expressed here as%0A     *%0A     *                new SomeSubClass(%22Schema%22, 4200,%0A     *                  %22page%22, %22List of mass murderers%22,%0A     *                  %22section%22, %222014%22%0A     *                );%0A     *%0A     *                This format should be only used in subclass constructors.%0A     *                The subclass constructors should take more explicit parameters%0A     *                depending on what they are logging.%0A     */%0A    protected EventLoggingEvent(String schema, int revID, String... payload) %7B%0A        data = new JSONObject();%0A        try %7B%0A            data.put(%22schema%22, schema);%0A            data.put(%22revision%22, revID);%0A%0A            JSONObject event = new JSONObject();%0A%0A            for (int i = 0; i %3C payload.length; i += 2) %7B%0A                event.put(payload%5Bi%5D, payload%5Bi+1%5D);%0A            %7D%0A%0A            data.put(%22event%22, event);%0A        %7D catch (JSONException e) %7B%0A            throw new RuntimeException(e);%0A        %7D%0A    %7D%0A%0A    /**%0A     * Log the current event.%0A     *%0A     * Returns immediately after queueing the network request in the background.%0A     */%0A    public void log() %7B%0A        new LogEventTask(data).execute();%0A    %7D%0A%0A    private static class LogEventTask extends SaneAsyncTask%3CBoolean%3E %7B%0A        private final JSONObject data;%0A        public LogEventTask(JSONObject data) %7B%0A            super(1);%0A            this.data = data;%0A        %7D%0A%0A        @Override%0A        public Boolean performTask() throws Throwable %7B%0A            String dataURL = Uri.parse(EVENTLOG_URL)%0A                    .buildUpon().query(data.toString())%0A                    .build().toString();%0A            return HttpRequest.get(dataURL).ok();%0A        %7D%0A%0A        @Override%0A        public void onCatch(Throwable caught) %7B%0A            // Do nothing bad. EL data is ok to lose.%0A            Log.d(%22Wikipedia%22, %22Lost EL data: %22 + data.toString());%0A        %7D%0A    %7D%0A%7D%0A

Add base class for EventLogging