mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[ex] 17284 AE: ComponentManagerImpl.getStateStore + Notification Model synchronization [r=jeka]
This commit is contained in:
@@ -20,6 +20,7 @@ import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.util.PairFunction;
|
||||
import com.intellij.util.concurrency.ReentrantLock2;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -35,6 +36,8 @@ public class NotificationModel {
|
||||
private final Map<Notification, Pair<Project, Boolean>> myNotifications = new LinkedHashMap<Notification, Pair<Project, Boolean>>();
|
||||
private final List<NotificationModelListener> myListeners = ContainerUtil.createEmptyCOWList();
|
||||
|
||||
private final ReentrantLock2 myLock = new ReentrantLock2();
|
||||
|
||||
public void addListener(@NotNull final NotificationModelListener listener) {
|
||||
myListeners.add(listener);
|
||||
}
|
||||
@@ -44,33 +47,59 @@ public class NotificationModel {
|
||||
}
|
||||
|
||||
public void add(@NotNull final Notification notification, final @Nullable Project project) {
|
||||
myNotifications.put(notification, Pair.create(project, false));
|
||||
try {
|
||||
myLock.acquire();
|
||||
myNotifications.put(notification, Pair.create(project, false));
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
|
||||
for (NotificationModelListener listener : myListeners) {
|
||||
listener.notificationsAdded(notification);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void markRead() {
|
||||
if (myNotifications.size() > 0) {
|
||||
final Collection<Notification> tba = myNotifications.keySet();
|
||||
List<Notification> changed = null;
|
||||
|
||||
try {
|
||||
myLock.acquire();
|
||||
if (myNotifications.isEmpty()) return;
|
||||
|
||||
changed = new ArrayList<Notification>();
|
||||
|
||||
for (final Map.Entry<Notification, Pair<Project, Boolean>> entry : myNotifications.entrySet()) {
|
||||
entry.setValue(new Pair<Project, Boolean>(entry.getValue().first, true));
|
||||
changed.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
|
||||
if (!changed.isEmpty()) {
|
||||
final Notification[] read = changed.toArray(new Notification[changed.size()]);
|
||||
for (final NotificationModelListener listener : myListeners) {
|
||||
listener.notificationsRead(tba.toArray(new Notification[tba.size()]));
|
||||
listener.notificationsRead(read);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Notification remove(@NotNull final Notification notification) {
|
||||
if (myNotifications.containsKey(notification)) {
|
||||
myNotifications.remove(notification);
|
||||
try {
|
||||
myLock.acquire();
|
||||
final Pair<Project, Boolean> pair = myNotifications.remove(notification);
|
||||
if (pair == null) return notification;
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
|
||||
for (NotificationModelListener listener : myListeners) {
|
||||
listener.notificationsRemoved(notification);
|
||||
}
|
||||
for (NotificationModelListener listener : myListeners) {
|
||||
listener.notificationsRemoved(notification);
|
||||
}
|
||||
|
||||
return notification;
|
||||
@@ -78,35 +107,49 @@ public class NotificationModel {
|
||||
|
||||
public void remove(@NotNull final Notification... notifications) {
|
||||
final List<Notification> tbr = new ArrayList<Notification>();
|
||||
for (final Notification notification : notifications) {
|
||||
if (myNotifications.containsKey(notification)) {
|
||||
tbr.add(notification);
|
||||
myNotifications.remove(notification);
|
||||
try {
|
||||
myLock.acquire();
|
||||
for (final Notification notification : notifications) {
|
||||
final Pair<Project, Boolean> pair = myNotifications.remove(notification);
|
||||
if (pair != null) {
|
||||
tbr.add(notification);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
|
||||
if (tbr.size() > 0) {
|
||||
if (!tbr.isEmpty()) {
|
||||
final Notification[] removed = tbr.toArray((Notification[])Array.newInstance(tbr.get(0).getClass(), tbr.size()));
|
||||
for (NotificationModelListener listener : myListeners) {
|
||||
listener.notificationsRemoved(tbr.toArray((Notification[])Array.newInstance(tbr.get(0).getClass(), tbr.size())));
|
||||
listener.notificationsRemoved(removed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Notification get(final int index, @NotNull PairFunction<Notification, Project, Boolean> filter) {
|
||||
final LinkedList<Notification> filtered = filterNotifications(filter);
|
||||
if (index >= 0 && filtered.size() > index) {
|
||||
return filtered.get(index);
|
||||
try {
|
||||
myLock.acquire();
|
||||
final List<Notification> filtered = filterNotifications(filter);
|
||||
if (index >= 0 && filtered.size() > index) {
|
||||
return filtered.get(index);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private LinkedList<Notification> filterNotifications(@NotNull PairFunction<Notification, Project, Boolean> filter) {
|
||||
final LinkedList<Notification> result = new LinkedList<Notification>();
|
||||
final HashSet<Map.Entry<Notification, Pair<Project, Boolean>>> entries =
|
||||
new HashSet<Map.Entry<Notification, Pair<Project, Boolean>>>(myNotifications.entrySet());
|
||||
for (final Map.Entry<Notification, Pair<Project, Boolean>> entry : entries) {
|
||||
private List<Notification> filterNotifications(@NotNull PairFunction<Notification, Project, Boolean> filter) {
|
||||
LinkedList<Notification> result;
|
||||
if (myNotifications.isEmpty()) return Collections.emptyList();
|
||||
|
||||
result = new LinkedList<Notification>();
|
||||
for (final Map.Entry<Notification, Pair<Project, Boolean>> entry : myNotifications.entrySet()) {
|
||||
if (filter.fun(entry.getKey(), entry.getValue().first)) {
|
||||
result.addFirst(entry.getKey());
|
||||
}
|
||||
@@ -116,7 +159,13 @@ public class NotificationModel {
|
||||
}
|
||||
|
||||
public int getCount(@NotNull PairFunction<Notification, Project, Boolean> filter) {
|
||||
return filterNotifications(filter).size();
|
||||
try {
|
||||
myLock.acquire();
|
||||
return filterNotifications(filter).size();
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty(@NotNull PairFunction<Notification, Project, Boolean> filter) {
|
||||
@@ -125,18 +174,25 @@ public class NotificationModel {
|
||||
|
||||
@Nullable
|
||||
public Notification getFirst(@NotNull PairFunction<Notification, Project, Boolean> filter) {
|
||||
final LinkedList<Notification> result = filterNotifications(filter);
|
||||
if (result.size() > 0) {
|
||||
return result.getFirst();
|
||||
try {
|
||||
myLock.acquire();
|
||||
final List<Notification> result = filterNotifications(filter);
|
||||
return result.isEmpty() ? null : result.get(0);
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void clear(@NotNull PairFunction<Notification, Project, Boolean> filter) {
|
||||
final LinkedList<Notification> result = filterNotifications(filter);
|
||||
for (final Notification notification : result) {
|
||||
myNotifications.remove(notification);
|
||||
List<Notification> result;
|
||||
try {
|
||||
myLock.acquire();
|
||||
result = filterNotifications(filter);
|
||||
myNotifications.keySet().removeAll(result);
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
|
||||
if (!result.isEmpty()) {
|
||||
@@ -149,28 +205,53 @@ public class NotificationModel {
|
||||
|
||||
public List<Notification> getByType(@Nullable final NotificationType type, @NotNull PairFunction<Notification, Project, Boolean> filter) {
|
||||
if (type == null) {
|
||||
return Collections.unmodifiableList(filterNotifications(filter));
|
||||
}
|
||||
else {
|
||||
final List<Notification> result = new ArrayList<Notification>();
|
||||
final LinkedList<Notification> filtered = filterNotifications(filter);
|
||||
for (final Notification notification : filtered) {
|
||||
if (type == notification.getType()) {
|
||||
result.add(notification);
|
||||
}
|
||||
try {
|
||||
myLock.acquire();
|
||||
return Collections.unmodifiableList(filterNotifications(filter));
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
final List<Notification> filtered;
|
||||
try {
|
||||
myLock.acquire();
|
||||
filtered = filterNotifications(filter);
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
|
||||
final List<Notification> result = new ArrayList<Notification>();
|
||||
for (final Notification notification : filtered) {
|
||||
if (type == notification.getType()) {
|
||||
result.add(notification);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean wasRead(final Notification notification) {
|
||||
final Pair<Project, Boolean> pair = myNotifications.get(notification);
|
||||
return pair != null && pair.second;
|
||||
try {
|
||||
myLock.acquire();
|
||||
final Pair<Project, Boolean> pair = myNotifications.get(notification);
|
||||
return pair != null && pair.second;
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasUnread(final PairFunction<Notification, Project, Boolean> filter) {
|
||||
return getUnreadCount(filter) > 0;
|
||||
try {
|
||||
myLock.acquire();
|
||||
return getUnreadCount(filter) > 0;
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
private int getUnreadCount(final PairFunction<Notification, Project, Boolean> filter) {
|
||||
@@ -182,12 +263,26 @@ public class NotificationModel {
|
||||
}
|
||||
|
||||
public boolean hasRead(PairFunction<Notification, Project, Boolean> filter) {
|
||||
return getUnreadCount(filter) < myNotifications.size();
|
||||
try {
|
||||
myLock.acquire();
|
||||
return getUnreadCount(filter) < myNotifications.size();
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public NotificationType getMaximumType(PairFunction<Notification, Project, Boolean> filter) {
|
||||
final LinkedList<Notification> notifications = filterNotifications(filter);
|
||||
final List<Notification> notifications;
|
||||
try {
|
||||
myLock.acquire();
|
||||
notifications = filterNotifications(filter);
|
||||
}
|
||||
finally {
|
||||
myLock.release();
|
||||
}
|
||||
|
||||
NotificationType result = null;
|
||||
for (Notification notification : notifications) {
|
||||
if (NotificationType.ERROR == notification.getType()) {
|
||||
|
||||
@@ -225,7 +225,7 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx {
|
||||
@Nullable
|
||||
@NonNls
|
||||
public String getLocation() {
|
||||
return getStateStore().getLocation();
|
||||
return isDisposed() ? null : getStateStore().getLocation();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
|
||||
Reference in New Issue
Block a user