20 package net.sf.gridarta.model.index;
22 import java.io.IOException;
23 import java.io.ObjectInputStream;
24 import java.io.ObjectOutputStream;
25 import java.io.Serializable;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.Iterator;
32 import java.util.Map.Entry;
33 import java.util.concurrent.CopyOnWriteArrayList;
34 import org.jetbrains.annotations.NotNull;
35 import org.jetbrains.annotations.Nullable;
49 private final Object
sync =
new Object();
55 private final Collection<IndexListener<V>>
indexListeners =
new CopyOnWriteArrayList<>();
69 private final Map<V, String>
names =
new HashMap<>();
76 private final Collection<V>
pending =
new HashSet<>();
105 synchronized (
sync) {
106 final String nameLowerCase =
name.toLowerCase();
107 final Collection<V> result =
new HashSet<>();
108 for (
final Entry<V, String> e :
names.entrySet()) {
109 if (e.getValue().toLowerCase().contains(nameLowerCase)) {
110 result.add(e.getKey());
119 synchronized (
sync) {
128 synchronized (
sync) {
130 throw new IllegalStateException(
"no transaction is active");
136 if (!tmp.isEmpty()) {
138 for (
final V value : tmp) {
143 for (
final V value : tmp) {
145 listener.valueRemoved(value);
146 listener.nameChanged();
154 public void add(@NotNull
final V value,
final long timestamp) {
155 synchronized (
sync) {
156 final Long oldTimestamp =
timestamps.put(value, timestamp);
157 final boolean notifyPending;
158 final boolean notifyAdded;
159 if (oldTimestamp ==
null || oldTimestamp != timestamp) {
161 notifyAdded = oldTimestamp ==
null;
164 notifyPending =
false;
170 listener.valueAdded(value);
175 listener.pendingChanged();
182 public void remove(@NotNull
final V value) {
183 synchronized (
sync) {
191 listener.valueRemoved(value);
192 listener.nameChanged();
199 synchronized (
sync) {
200 final boolean notifyPending =
pending.add(value) &&
pending.size() == 1;
205 listener.valueAdded(value);
210 listener.pendingChanged();
217 public void setName(@NotNull
final V value,
final long timestamp, @NotNull
final String
name) {
218 synchronized (
sync) {
220 final String oldName =
names.put(value,
name);
221 if (oldName !=
null && oldName.equals(
name)) {
226 listener.nameChanged();
233 public String
getName(@NotNull
final V value) {
234 synchronized (
sync) {
235 return names.get(value);
242 synchronized (
sync) {
243 final Iterator<V>
it =
pending.iterator();
248 final V result =
it.next();
256 synchronized (
sync) {
263 synchronized (
sync) {
279 public void save(@NotNull
final ObjectOutputStream objectOutputStream)
throws IOException {
280 synchronized (
sync) {
282 objectOutputStream.writeObject(
names);
291 @SuppressWarnings(
"unchecked")
292 public
void load(@NotNull final ObjectInputStream objectInputStream) throws IOException {
293 synchronized (
sync) {
294 final Map<V, Long> tmpTimestamps;
295 final Map<V, String> tmpNames;
297 tmpTimestamps = (Map<V, Long>) objectInputStream.readObject();
298 tmpNames = (Map<V, String>) objectInputStream.readObject();
299 }
catch (
final ClassNotFoundException ex) {
300 throw new IOException(ex.getMessage(), ex);
303 throw new IOException(
"cannot restore state within active transaction");
307 tmpNames.keySet().retainAll(tmpTimestamps.keySet());
311 names.putAll(tmpNames);
317 synchronized (
sync) {
329 listener.indexingFinished();