<commit_before>/* 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.service.stumblerthread.datahandling;

import org.mozilla.mozstumbler.service.Prefs;
import org.mozilla.mozstumbler.service.utils.Zipper;

import java.util.concurrent.ConcurrentLinkedQueue;

/*
 ReportBatchBuilder accepts MLS GeoSubmit JSON blobs and serializes them to
 string form.  This is
 */
public class ReportBatchBuilder {
    // The max number of reports stored in the mCachedReportBatches. Each report is a GPS location plus wifi and cell scan.
    // Once this size is reached, data is persisted to disk, mCachedReportBatches is cleared.
    public static final int MAX_REPORTS_IN_MEMORY = 50;

    private ConcurrentLinkedQueue<MLSJSONObject> mReportList = new ConcurrentLinkedQueue<MLSJSONObject>();

    public int reportsCount() {
        return mReportList.size();
    }

    /*
     This dequeues all collected reports and generates a stringified JSON blob

     Setting preserveReports to true will ensure that the reports are not lost after being
     converted to a string.  You almost certainly want to set that flag to false though as you'll
     eat memory.
     */
    byte[] finalizeAndClearReports() {
        return Zipper.zipData(generateJSON(false).getBytes());
    }

    private String generateJSON(boolean preserveReports) {

        ConcurrentLinkedQueue<MLSJSONObject> jsonCollector = new ConcurrentLinkedQueue<MLSJSONObject>();
        MLSJSONObject report = null;
        final String kPrefix = "{\"items\":[";
        StringBuilder reportString = new StringBuilder(kPrefix);
        report = mReportList.poll();
        if (report != null) {
            if (preserveReports) {
                jsonCollector.add(report);
            }
            reportString.append(report.toString());
        }

        report = mReportList.poll();
        while (report != null) {
            if (preserveReports) {
                jsonCollector.add(report);
            }
            reportString.append("," + report.toString());
            report = mReportList.poll();
        }

        // Restore the ejected reports if necessary
        if (preserveReports) {
            report = jsonCollector.poll();
            while (report != null) {
                mReportList.add(report);
                report = jsonCollector.poll();
            }
        }

        return reportString.toString() + "]}";
    }


    public void addReport(MLSJSONObject geoSubmitObj) {

        if (reportsCount() == MAX_REPORTS_IN_MEMORY) {
            // This can happen in the event that serializing reports to disk fails
            // and the reports list is never cleared.
            return;
        }
        mReportList.add(geoSubmitObj);
    }

    public boolean maxReportsReached() {
        // Always try to flush memory to storage if saving stumble logs is enabled.
        if (Prefs.getInstanceWithoutContext().isSaveStumbleLogs()) {
            return true;<commit_msg>Changed JSON construction as per code review<commit_after>/* 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.service.stumblerthread.datahandling;

import org.mozilla.mozstumbler.service.Prefs;
import org.mozilla.mozstumbler.service.utils.Zipper;

import java.util.concurrent.ConcurrentLinkedQueue;

/*
 ReportBatchBuilder accepts MLS GeoSubmit JSON blobs and serializes them to
 string form.  This is
 */
public class ReportBatchBuilder {
    // The max number of reports stored in the mCachedReportBatches. Each report is a GPS location plus wifi and cell scan.
    // Once this size is reached, data is persisted to disk, mCachedReportBatches is cleared.
    public static final int MAX_REPORTS_IN_MEMORY = 50;

    private ConcurrentLinkedQueue<MLSJSONObject> mReportList = new ConcurrentLinkedQueue<MLSJSONObject>();

    public int reportsCount() {
        return mReportList.size();
    }

    /*
     This dequeues all collected reports and generates a stringified JSON blob

     Setting preserveReports to true will ensure that the reports are not lost after being
     converted to a string.  You almost certainly want to set that flag to false though as you'll
     eat memory.
     */
    byte[] finalizeAndClearReports() {
        return Zipper.zipData(generateJSON(false).getBytes());
    }

    private String generateJSON(boolean preserveReports) {

        ConcurrentLinkedQueue<MLSJSONObject> jsonCollector = new ConcurrentLinkedQueue<MLSJSONObject>();
        MLSJSONObject report = null;
        final String kPrefix = "{\"items\":[";
        StringBuilder reportString = new StringBuilder(kPrefix);

        // Note that this is a blank separator for first iteration
        String jsonSep = "";

        report = mReportList.poll();
        while (report != null) {
            if (preserveReports) {
                jsonCollector.add(report);
            }
            reportString.append(jsonSep + report.toString());
            report = mReportList.poll();
            jsonSep = ",";
        }

        // Restore the ejected reports if necessary
        if (preserveReports) {
            report = jsonCollector.poll();
            while (report != null) {
                mReportList.add(report);
                report = jsonCollector.poll();
            }
        }

        return reportString.toString() + "]}";
    }


    public void addReport(MLSJSONObject geoSubmitObj) {

        if (reportsCount() == MAX_REPORTS_IN_MEMORY) {
            // This can happen in the event that serializing reports to disk fails
            // and the reports list is never cleared.
            return;
        }
        mReportList.add(geoSubmitObj);
    }

    public boolean maxReportsReached() {
        // Always try to flush memory to storage if saving stumble logs is enabled.
        if (Prefs.getInstanceWithoutContext().isSaveStumbleLogs()) {
            return true;
{'fraction_non_alphanumeric': 0.0812720848056537, 'fraction_numerical': 0.0019274012206874397, 'mean_word_length': 2.5441092771770064, 'pattern_counts': {'":': 2, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6895229', 'n_tokens_mistral': 1676, 'n_tokens_neox': 1596, 'n_words': 535}