package com.dataart.android.devicehive.client.commands;
import java.io.Serializable;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import com.dataart.android.devicehive.Notification;
import com.dataart.android.devicehive.network.DeviceHiveResultReceiver;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
/**
* Poll {@link Notification}s from given devices starting from given timestamp.
* This request returns immediately if there have been any notifications since
* given timestamp. In the case when no notifications were found, the method
* blocks until new notification is received. The blocking period is limited
* (currently 30 seconds). As a result returns list of {@link Notification}.
*/
public class PollMultipleDeviceNotificationsCommand extends
PollNotificationsCommand {
protected final List<String> deviceIds;
/**
* Construct command for given device and last received notification
* timestamp.
*
* @param deviceIds
* List of device identifiers.
* @param lastNotificationPollTimestamp
* Last received notification timestamp.
*/
public PollMultipleDeviceNotificationsCommand(List<String> deviceIds,
String lastNotificationPollTimestamp) {
this(deviceIds, lastNotificationPollTimestamp, null);
}
/**
* Construct a new command.
*
* @param deviceIds
* List of device identifiers.
* @param lastNotificationPollTimestamp
* Timestamp which defines starting point in the past for
* notifications.
* @param waitTimeout
* Waiting timeout in seconds.
*/
public PollMultipleDeviceNotificationsCommand(List<String> deviceIds,
String lastNotificationPollTimestamp, Integer waitTimeout) {
super(lastNotificationPollTimestamp, waitTimeout);
this.deviceIds = deviceIds;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeStringList(deviceIds);
super.writeToParcel(dest, flags);
}
public static Parcelable.Creator<PollMultipleDeviceNotificationsCommand> CREATOR = new Parcelable.Creator<PollMultipleDeviceNotificationsCommand>() {
@Override
public PollMultipleDeviceNotificationsCommand[] newArray(int size) {
return new PollMultipleDeviceNotificationsCommand[size];
}
@Override
public PollMultipleDeviceNotificationsCommand createFromParcel(
Parcel source) {
List<String> deviceIds = new LinkedList<String>();
source.readStringList(deviceIds);
return new PollMultipleDeviceNotificationsCommand(deviceIds,
source.readString(),
(Integer) source.readValue(CLASS_LOADER));
}
};
@Override
protected String getRequestPath() {
String requestPath = "device/notification/poll";
if (isDeviceGuidsPresent()) {
requestPath += String.format("?deviceGuids=%s",
prepareGuidsString(deviceIds));
}
if (lastNotificationPollTimestamp != null) {
requestPath += isDeviceGuidsPresent() ? "&" : "?";
requestPath += "timestamp="
+ encodedString(lastNotificationPollTimestamp);
}
if (waitTimeout != null) {
requestPath += (isDeviceGuidsPresent() || lastNotificationPollTimestamp != null) ? "&"
: "?";
requestPath += "waitTimeout=" + waitTimeout;
}
return requestPath;
}
private boolean isDeviceGuidsPresent() {
return deviceIds != null && !deviceIds.isEmpty();
}
private String prepareGuidsString(List<String> guids) {
if (deviceIds == null || deviceIds.isEmpty()) {
return null;
} else {
final StringBuilder builder = new StringBuilder("");
String separator = "";
for (String guid : guids) {
builder.append(separator).append(guid);
separator = ",";
}
return builder.toString();
}
}
public static class DeviceNotification extends Notification {
private String deviceGuid;
public String getDeviceGuid() {
return deviceGuid;
}
/* package */DeviceNotification(int id, String name, String timestamp,
Serializable parameters) {
super(id, name, timestamp, parameters);
}
/* package */DeviceNotification(String deviceGuid,
Notification notification) {
super(notification.getId(), notification.getName(), notification
.getTimestamp(), notification.getParameters());
this.deviceGuid = deviceGuid;
}
}
private static class DeviceGuidNotification {
String deviceGuid;
Notification notification;
}
@Override
protected int fromJson(final String response, final Gson gson,
final Bundle resultData) {
Type listType = new TypeToken<ArrayList<DeviceGuidNotification>>() {
}.getType();
ArrayList<DeviceGuidNotification> notifications = gson.fromJson(
response, listType);
resultData.putParcelableArrayList(NOTIFICATIONS_KEY,
asDeviceNotificationList(notifications));
return DeviceHiveResultReceiver.MSG_HANDLED_RESPONSE;
}
private static ArrayList<DeviceNotification> asDeviceNotificationList(
List<DeviceGuidNotification> notifications) {
ArrayList<DeviceNotification> result = new ArrayList<DeviceNotification>(
notifications.size());
for (DeviceGuidNotification guidNotification : notifications) {
result.add(new DeviceNotification(guidNotification.deviceGuid,
guidNotification.notification));
}
return result;
}
}