package ns.foundation;
import java.util.EnumSet;
import java.util.Set;
public class NSNotificationQueue extends NSObject {
public enum NSPostingStyle {
WhenIdle,
ASAP,
Now
}
public enum NSNotificationCoalescing {
OnName,
OnSender
}
private static final NSNotificationQueue _defaultQueue = new NSNotificationQueue();
private transient final NSNotificationCenter _center;
private transient final NSMutableArray<NSNotificationQueueEntry> _asapQueue = new NSMutableArray<NSNotificationQueueEntry>();
private transient final NSMutableArray<NSNotificationQueueEntry> _idleQueue = new NSMutableArray<NSNotificationQueueEntry>();
public static NSNotificationQueue defaultQueue() {
return _defaultQueue;
}
public NSNotificationQueue() {
this(NSNotificationCenter.defaultCenter());
}
private class NSNotificationQueueEntry {
private final NSArray<String> _modes;
private final NSNotification _notification;
NSNotificationQueueEntry(NSNotification notification, NSArray<String> modes) {
_notification = notification;
_modes = modes;
}
public NSNotification notification() {
return _notification;
}
public NSArray<String> modes() {
return _modes;
}
}
public void asapProcessMode(String mode) {
boolean hasNotifications = false;
do {
int count = _asapQueue.count();
hasNotifications = false;
for (int i = 0; i < count && !hasNotifications; i++) {
NSNotificationQueueEntry qd = _asapQueue.objectAtIndex(i);
NSArray<String> modes = qd.modes();
if (modes == null || modes.containsObject(mode)) {
_asapQueue.removeObjectAtIndex(i);
hasNotifications = true;
_center.postNotification(qd.notification());
}
}
} while (hasNotifications);
}
public boolean hasIdleNotificationsInMode(String mode) {
int count = _idleQueue.count();
while (--count >= 0) {
NSNotificationQueueEntry check = _idleQueue.objectAtIndex(count);
NSArray<String> modes = check.modes();
if (modes == null || modes.containsObject(mode)) {
return true;
}
}
return false;
}
public void idleProcessMode(String mode) {
NSMutableArray<NSNotificationQueueEntry> idle = new NSMutableArray<NSNotificationQueueEntry>();
int count = _idleQueue.count();
while (--count >= 0) {
NSNotificationQueueEntry check = _idleQueue.objectAtIndex(count);
NSArray<String> modes = check.modes();
if (modes == null || modes.containsObject(mode)) {
idle.addObject(check);
_idleQueue.removeObjectAtIndex(count);
}
}
count = idle.count();
while (--count >= 0) {
NSNotificationQueueEntry check = idle.objectAtIndex(count);
_center.postNotification(check.notification());
}
}
protected void coalesceNotificationInQueueWithCoalesceMask(NSNotification notification, NSMutableArray<NSNotificationQueueEntry> queue, Set<NSNotificationCoalescing> coalesceMask) {
if (coalesceMask != null && !coalesceMask.isEmpty()) {
int count = queue.count();
while(--count >= 0) {
NSNotification check = queue.objectAtIndex(count).notification();
boolean remove = false;
if (coalesceMask.contains(NSNotificationCoalescing.OnName)) {
if (check.name().equals(notification.name())) {
remove = true;
}
}
if (coalesceMask.contains(NSNotificationCoalescing.OnSender)) {
if (check.object() == notification.object()) {
remove = true;
}
}
if (remove) {
queue.removeObjectAtIndex(count);
}
}
}
}
protected boolean canPlaceNotificationInQueueWithCoalesceMask(NSNotification notification, NSMutableArray<NSNotificationQueueEntry> queue, Set<NSNotificationCoalescing> coalesceMask) {
if (coalesceMask != null && !coalesceMask.isEmpty()) {
int count = queue.count();
for (int i = 0; i < count; i++) {
NSNotification check = queue.objectAtIndex(i).notification();
if (coalesceMask.contains(NSNotificationCoalescing.OnName)) {
if (check.name().equals(notification.name())) {
return false;
}
}
if (coalesceMask.contains(NSNotificationCoalescing.OnSender)) {
if (check.name().equals(notification.object())) {
return false;
}
}
}
}
return true;
}
public NSNotificationQueue(NSNotificationCenter notificationCenter) {
_center = notificationCenter;
}
public void enqueueNotification(NSNotification notification, NSPostingStyle postingStyle) {
enqueueNotificationWithCoalesceMaskForModes(notification, postingStyle, EnumSet.of(NSNotificationCoalescing.OnName, NSNotificationCoalescing.OnSender), null);
}
public void enqueueNotificationWithCoalesceMaskForModes(NSNotification notification, NSPostingStyle postingStyle, Set<NSNotificationCoalescing> coalesceMask, NSArray<String> modes) {
if (postingStyle == null) {
throw new IllegalArgumentException("postingStyle cannot be null");
}
if (postingStyle == NSPostingStyle.Now) {
_center.postNotification(notification);
} else {
NSMutableArray<NSNotificationQueueEntry> queue = null;
if (postingStyle == NSPostingStyle.WhenIdle) {
queue = _idleQueue;
} else {
queue = _asapQueue;
}
coalesceNotificationInQueueWithCoalesceMask(notification, queue, coalesceMask);
if (canPlaceNotificationInQueueWithCoalesceMask(notification, queue, coalesceMask)) {
queue.addObject(new NSNotificationQueueEntry(notification, modes));
}
}
}
public void dequeueMatchingNotifications(NSNotification notification, Set<NSNotificationCoalescing> coalesceMask) {
dequeueNotificationInQueueWithCoalesceMask(notification, _idleQueue, coalesceMask);
dequeueNotificationInQueueWithCoalesceMask(notification, _asapQueue, coalesceMask);
}
protected void dequeueNotificationInQueueWithCoalesceMask(NSNotification notification, NSMutableArray<NSNotificationQueueEntry> queue, Set<NSNotificationCoalescing> coalesceMask) {
int count = queue.count();
while(--count >= 0) {
NSNotification check = queue.objectAtIndex(count).notification();
boolean remove = false;
if (coalesceMask == null || coalesceMask.isEmpty()) {
if (notification.equals(check)) {
remove = true;
}
} else {
if (coalesceMask.contains(NSNotificationCoalescing.OnName)) {
if (check.name().equals(notification.name())) {
remove = true;
}
}
if (coalesceMask.contains(NSNotificationCoalescing.OnSender)) {
if (check.object() == notification.object()) {
remove = true;
}
}
}
if (remove) {
queue.removeObjectAtIndex(count);
}
}
}
}