/*
* 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/.
*
* Copyright (c) 2014 Digi International Inc., All Rights Reserved.
*/
package com.digi.android.wva.util;
import com.digi.android.wva.model.VehicleData;
import java.util.LinkedList;
/**
* Class containing static LinkedLists used as queues for sending
* messages and data from various sources (like {@link com.digi.android.wva.VehicleInfoService}
* and {@link com.digi.android.wva.WvaApplication}) to the
* {@link com.digi.android.wva.DashboardActivity} and {@link com.digi.android.wva.fragments.ChartFragment}
* for use.
*
* Created by mwadsten on 5/22/13.
*/
public class MessageCourier {
/**
* Wrapper around data (pertaining to device connection status) to be
* processed by the DashboardActivity.
*/
public static class DashboardMessage {
final String data;
final boolean isError, isReconnecting;
private DashboardMessage(String data, boolean isError, boolean isReconnect) {
this.data = data;
this.isError = isError;
this.isReconnecting = isReconnect;
}
/**
* Get the string held in this message
* @return the string data held by this message
*/
public String getContents() {
return data;
}
/**
* Get the boolean held in this message (indicating if this message
* signifies an error or not)
* @return true if this message indicates an error
*/
public boolean isError() {
return isError;
}
public boolean isReconnecting() {
return isReconnecting;
}
/**
* Create a new {@link DashboardMessage} to report that connecting
* to the device at <b>ip</b> was successful.
* @param ip IP address we are connected to
* @return new {@link DashboardMessage} containing the IP address
*/
public static DashboardMessage connected(String ip) {
return new DashboardMessage(ip, false, false);
}
/**
* Create a new {@link DashboardMessage} to report that some error
* has occurred.
* @param error a String message to indicate the error
* @return new {@link DashboardMessage} containing the error message
*/
public static DashboardMessage error(String error) {
return new DashboardMessage(error, true, false);
}
public static DashboardMessage reconnecting(String ip) {
return new DashboardMessage(ip, false, true);
}
}
/**
* Wrapper around data to be processed by the ChartFragment.
*/
public static class ChartMessage {
String error;
VehicleData data;
boolean isReconnecting;
/**
* Get the error string passed in when creating this message, if any
* @return error string contained within, or null if none
*/
public String getError() {
return error;
}
/**
* Get the {@link VehicleData} object passed in when creating this
* message, if any
* @return VehicleData contained within, or null if none
*/
public VehicleData getData() {
return data;
}
public boolean isReconnecting() {
return isReconnecting;
}
/**
* Create a new {@link ChartMessage} to indicate that an error
* has occurred within the application
* @param error error string to pass along
* @return new {@link ChartMessage} containing the error
*/
public static ChartMessage error(String error) {
ChartMessage rv = new ChartMessage();
rv.error = error;
rv.isReconnecting = false;
return rv;
}
/**
* Create a new {@link ChartMessage} to indicate that new vehicle
* data has arrived and should be plotted on the graph
* @param data {@link VehicleData} to plot
* @return new {@link ChartMessage} containing the data
*/
public static ChartMessage newData(VehicleData data) {
ChartMessage rv = new ChartMessage();
rv.data = data;
rv.isReconnecting = false;
return rv;
}
public static ChartMessage reconnecting() {
ChartMessage rv = new ChartMessage();
rv.isReconnecting = true;
return rv;
}
}
private static final LinkedList<DashboardMessage> toDash = new LinkedList<DashboardMessage>();
private static final LinkedList<ChartMessage> toChart = new LinkedList<ChartMessage>();
private static final int DASH_MAX = 5;
private static final int CHART_MAX = 20;
private static final Object dashlock = new Object(),
chartlock = new Object();
/**
* No need for a constructor for MessageCourier.
*/
private MessageCourier() {}
/**
* Queue up a new message for the dashboard to inform it that
* we have successfully connected to a device.
* @param ipaddress IP address we are connected to
*/
public static void sendDashConnected(String ipaddress) {
putDashMessage(DashboardMessage.connected(ipaddress));
}
/**
* Queue up a new message for both the dashboard and the chart, notifying
* them that there has been a connection error with the device.
*
* <p>The error message gets placed at the front of the message "queues";
* this way, the error will be processed before other messages, such as
* "connected"/"reconnecting" messages.</p>
* @param error error message to display
*/
public static void sendError(String error) {
putDashMessage(DashboardMessage.error(error), true);
putChartMessage(ChartMessage.error(error), true);
}
public static void sendReconnecting(String ipaddress) {
putDashMessage(DashboardMessage.reconnecting(ipaddress));
putChartMessage(ChartMessage.reconnecting());
}
/**
* Queue up a new message for the chart, giving it new vehicle data to plot.
* @param data VehicleData object to plot on screen
*/
public static void sendChartNewData(VehicleData data) {
putChartMessage(ChartMessage.newData(data));
}
private static void putDashMessage(DashboardMessage msg) {
putDashMessage(msg, false);
}
private static void putDashMessage(DashboardMessage msg, boolean putAtFront) {
synchronized (dashlock) {
if (putAtFront)
toDash.addFirst(msg);
else
toDash.add(msg);
// Keep dashboard message queue to an appropriate size.
while (toDash.size() > DASH_MAX) {
toDash.remove();
}
}
}
private static void putChartMessage(ChartMessage msg) {
putChartMessage(msg, false);
}
private static void putChartMessage(ChartMessage msg, boolean putAtFront) {
synchronized (chartlock) {
if (putAtFront)
toChart.addFirst(msg);
else
toChart.add(msg);
// Keep chart message queue to an appropriate size.
while (toChart.size() > CHART_MAX) {
toChart.remove();
}
}
}
/**
* Retrieve all DashboardMessages currently queued up, as an array.
* @return all currently enqueued DashboardMessages, or an empty array if
* there are none
*/
public static DashboardMessage[] getDashboardMessages() {
synchronized (dashlock) {
final int count = toDash.size();
if (count <= 0)
return new DashboardMessage[0];
DashboardMessage[] msgs = new DashboardMessage[count];
toDash.toArray(msgs);
toDash.clear();
return msgs;
}
}
/**
* Retrieve all ChartMessages currently queued up, as an array.
* @return all currently enqueued ChartMessages, or an empty array if
* there are none
*/
public static ChartMessage[] getChartMessages() {
synchronized (chartlock) {
final int count = toChart.size();
if (count <= 0)
return new ChartMessage[0];
ChartMessage[] msgs = new ChartMessage[count];
toChart.toArray(msgs);
toChart.clear();
return msgs;
}
}
/**
* Clear out any pending {@link ChartMessage}s and {@link DashboardMessage}s.
*/
public static void clear() {
synchronized (chartlock) {
toChart.clear();
}
synchronized (dashlock) {
toDash.clear();
}
}
}