org.envirocar.app.json.TrackEncoder.java Source code

Java tutorial

Introduction

Here is the source code for org.envirocar.app.json.TrackEncoder.java

Source

/* 
 * enviroCar 2013
 * Copyright (C) 2013  
 * Martin Dueren, Jakob Moellers, Gerald Pape, Christopher Stephan
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 * 
 */
package org.envirocar.app.json;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.envirocar.app.exception.MeasurementsException;
import org.envirocar.app.logging.Logger;
import org.envirocar.app.storage.Measurement;
import org.envirocar.app.storage.Track;
import org.envirocar.app.storage.Measurement.PropertyKey;
import static org.envirocar.app.storage.Measurement.PropertyKey.*;
import org.envirocar.app.util.Util;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class TrackEncoder {

    private static final Logger logger = Logger.getLogger(TrackEncoder.class);

    public static final Set<PropertyKey> supportedPhenomenons = new HashSet<PropertyKey>();

    static {
        supportedPhenomenons.add(CALCULATED_MAF);
        supportedPhenomenons.add(MAF);
        supportedPhenomenons.add(CO2);
        supportedPhenomenons.add(SPEED);
        supportedPhenomenons.add(RPM);
        supportedPhenomenons.add(INTAKE_PRESSURE);
        supportedPhenomenons.add(INTAKE_TEMPERATURE);
        supportedPhenomenons.add(CONSUMPTION);
        supportedPhenomenons.add(ENGINE_LOAD);
        supportedPhenomenons.add(THROTTLE_POSITON);
        supportedPhenomenons.add(GPS_ACCURACY);
        supportedPhenomenons.add(GPS_ALTITUDE);
        supportedPhenomenons.add(GPS_BEARING);
        supportedPhenomenons.add(GPS_HDOP);
        supportedPhenomenons.add(GPS_PDOP);
        supportedPhenomenons.add(GPS_VDOP);
        supportedPhenomenons.add(GPS_SPEED);
        supportedPhenomenons.add(SHORT_TERM_TRIM_1);
        supportedPhenomenons.add(LONG_TERM_TRIM_1);
        supportedPhenomenons.add(LAMBDA_CURRENT);
        supportedPhenomenons.add(LAMBDA_CURRENT_ER);
        supportedPhenomenons.add(LAMBDA_VOLTAGE);
        supportedPhenomenons.add(LAMBDA_VOLTAGE_ER);
        supportedPhenomenons.add(FUEL_SYSTEM_LOOP);
        supportedPhenomenons.add(FUEL_SYSTEM_STATUS_CODE);
    }

    /**
     * Converts Track Object into track.create.json string
     * 
     * @return
     * @throws JSONException 
     * @throws TrackWithoutMeasurementsException 
     */
    public JSONObject createTrackJson(Track track, boolean obfuscate)
            throws JSONException, TrackWithoutMeasurementsException {
        JSONObject result = new JSONObject();

        String trackSensorName = track.getCar().getId();

        ArrayList<JSONObject> measurementElements = new ArrayList<JSONObject>();

        List<Measurement> measurements = getNonObfuscatedMeasurements(track, obfuscate);

        if (measurements == null || measurements.isEmpty()) {
            throw new TrackWithoutMeasurementsException("Track did not contain any non obfuscated measurements.");
        }

        for (Measurement measurement : measurements) {
            JSONObject measurementJson = createMeasurementJson(track, trackSensorName, measurement);
            measurementElements.add(measurementJson);
        }

        result.put("type", "FeatureCollection");
        result.put("features", new JSONArray(measurementElements));
        result.put("properties", createTrackProperties(track, trackSensorName));

        return result;
    }

    /**
     * resolve all not obfuscated measurements of a track.
     * 
     * This returns all measurements, if obfuscation is disabled. Otherwise
     * measurements within the first and last minute and those within the start/end
     * radius of 250 m are ignored (only if they are in the beginning/end of the track).
     * 
     * @param track
     * @return
     */
    public List<Measurement> getNonObfuscatedMeasurements(Track track, boolean obfuscate) {
        List<Measurement> measurements = track.getMeasurements();

        if (obfuscate) {
            boolean wasAtLeastOneTimeNotObfuscated = false;
            ArrayList<Measurement> privateCandidates = new ArrayList<Measurement>();
            ArrayList<Measurement> nonPrivateMeasurements = new ArrayList<Measurement>();
            for (Measurement measurement : measurements) {
                try {
                    /*
                     * ignore early and late
                     */
                    if (isTemporalObfuscationCandidate(measurement, track)) {
                        continue;
                    }

                    /*
                     * ignore distance
                     */
                    if (isSpatialObfuscationCandidate(measurement, track)) {
                        if (wasAtLeastOneTimeNotObfuscated) {
                            privateCandidates.add(measurement);
                            nonPrivateMeasurements.add(measurement);
                        }
                        continue;
                    }

                    /*
                     * we may have found obfuscation candidates in the middle of the track
                     * (may cross start or end point) in a PRIOR iteration
                     * of this loop. these candidates can be removed now as we are again
                     * out of obfuscation scope
                     */
                    if (wasAtLeastOneTimeNotObfuscated) {
                        privateCandidates.clear();
                    } else {
                        wasAtLeastOneTimeNotObfuscated = true;
                    }

                    nonPrivateMeasurements.add(measurement);
                } catch (MeasurementsException e) {
                    logger.warn(e.getMessage(), e);
                }

            }
            /*
             * the private candidates which have made it until here
             * shall be ignored
             */
            nonPrivateMeasurements.removeAll(privateCandidates);
            return nonPrivateMeasurements;
        }

        return measurements;
    }

    private boolean isSpatialObfuscationCandidate(Measurement measurement, Track track) {
        return (Util.getDistance(track.getFirstMeasurement(), measurement) <= 0.25)
                || (Util.getDistance(track.getLastMeasurement(), measurement) <= 0.25);
    }

    private boolean isTemporalObfuscationCandidate(Measurement measurement, Track track)
            throws MeasurementsException {
        return (measurement.getTime() - track.getStartTime() <= 60000
                || track.getEndTime() - measurement.getTime() <= 60000);
    }

    private JSONObject createTrackProperties(Track track, String trackSensorName) throws JSONException {
        JSONObject result = new JSONObject();

        result.put("sensor", trackSensorName);
        result.put("description", track.getDescription());
        result.put("name", track.getName());

        if (track.getMetadata() != null) {
            JSONObject json = track.getMetadata().toJson();
            JSONArray names = json.names();
            for (int i = 0; i < names.length(); i++) {
                result.put(names.get(i).toString(), json.getString(names.get(i).toString()));
            }
        }

        return result;
    }

    private JSONObject createMeasurementJson(Track track, String trackSensorName, Measurement measurement)
            throws JSONException {
        JSONObject result = new JSONObject();
        result.put("type", "Feature");

        result.put("geometry", createGeometry(measurement));
        result.put("properties", createMeasurementProperties(measurement, trackSensorName));

        return result;
    }

    private JSONObject createGeometry(Measurement measurement) throws JSONException {
        JSONObject result = new JSONObject();
        result.put("type", "Point");

        ArrayList<Double> coords = new ArrayList<Double>(2);
        coords.add(measurement.getLongitude());
        coords.add(measurement.getLatitude());

        result.put("coordinates", new JSONArray(coords));
        return result;
    }

    private JSONObject createMeasurementProperties(Measurement measurement, String trackSensorName)
            throws JSONException {
        JSONObject result = new JSONObject();
        result.put("sensor", trackSensorName);
        JSONObject phens = createPhenomenons(measurement);
        if (phens != null && phens.length() > 0) {
            result.put("phenomenons", phens);
        }
        result.put("time", Util.longToIsoDate(measurement.getTime()));
        return result;
    }

    private JSONObject createPhenomenons(Measurement measurement) throws JSONException {
        JSONObject result = new JSONObject();
        Map<PropertyKey, Double> props = measurement.getAllProperties();
        for (PropertyKey key : props.keySet()) {
            if (supportedPhenomenons.contains(key)) {
                result.put(key.toString(), createValue(props.get(key)));
            }
        }
        return result;
    }

    private JSONObject createValue(Double double1) throws JSONException {
        JSONObject result = new JSONObject();
        result.put("value", double1);
        return result;
    }
}