• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gephi / graphstore / #592

08 Oct 2026 07:01PM UTC coverage: 91.154% (+0.02%) from 91.138%
#592

push

web-flow
Restore id-only credential matching for the CI deploy (#305)

Maven 3.10 on the GitHub runners scopes server credentials to declared
origins, so the 'central' credentials were not sent to central.sonatype.com
and the snapshot deploy failed with HTTP 401.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

11923 of 13080 relevant lines covered (91.15%)

0.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.93
/src/main/java/org/gephi/graph/impl/TimeIndexStore.java
1
/*
2
 * Copyright 2012-2013 Gephi Consortium
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5
 * use this file except in compliance with the License. You may obtain a copy of
6
 * the License at
7
 *
8
 * http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
 * License for the specific language governing permissions and limitations under
14
 * the License.
15
 */
16
package org.gephi.graph.impl;
17

18
import it.unimi.dsi.fastutil.ints.IntRBTreeSet;
19
import it.unimi.dsi.fastutil.ints.IntSortedSet;
20
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
21
import java.util.Iterator;
22
import java.util.Map;
23
import java.util.Map.Entry;
24
import org.gephi.graph.api.DirectedSubgraph;
25
import org.gephi.graph.api.Edge;
26
import org.gephi.graph.api.Element;
27
import org.gephi.graph.api.Graph;
28
import org.gephi.graph.api.GraphView;
29
import org.gephi.graph.api.Node;
30
import org.gephi.graph.api.TimeIndex;
31
import org.gephi.graph.api.types.TimeMap;
32
import org.gephi.graph.api.types.TimeSet;
33
import org.gephi.graph.impl.utils.MapDeepEquals;
34

35
public abstract class TimeIndexStore<T extends Element, K, S extends TimeSet<K>, M extends TimeMap<K, ?>> {
36

37
    // Lock
38
    protected final TableLockImpl lock;
39
    // Element
40
    protected final Class<T> elementType;
41
    // Timestamp index management
42
    protected final Map<K, Integer> timeSortedMap;
43
    protected final IntSortedSet garbageQueue;
44
    protected int[] countMap;
45
    protected int length;
46
    // Index
47
    protected TimeIndexImpl mainIndex;
48
    protected final Map<GraphView, TimeIndexImpl> viewIndexes;
49

50
    protected TimeIndexStore(Class<T> type, TableLockImpl lock, boolean indexed, Map<K, Integer> sortedMap) {
1 ✔
51
        this.elementType = type;
1 ✔
52
        this.lock = lock;
1 ✔
53

54
        garbageQueue = new IntRBTreeSet();
1 ✔
55
        // Subclass
56
        timeSortedMap = sortedMap;
1 ✔
57
        countMap = new int[0];
1 ✔
58

59
        viewIndexes = indexed ? new Object2ObjectOpenHashMap<>() : null;
1 ✔
60
    }
1 ✔
61

62
    protected abstract void checkK(K k);
63

64
    protected abstract double getLow(K k);
65

66
    protected abstract TimeIndexImpl createIndex(boolean main);
67

68
    protected Integer add(K k) {
69
        checkK(k);
1 ✔
70

71
        lock();
1 ✔
72
        try {
73
            Integer id = timeSortedMap.get(k);
1 ✔
74
            if (id == null) {
1 ✔
75
                if (!garbageQueue.isEmpty()) {
1 ✔
76
                    id = garbageQueue.firstInt();
1 ✔
77
                    garbageQueue.remove(id);
1 ✔
78
                } else {
79
                    id = length++;
1 ✔
80
                }
81
                timeSortedMap.put(k, id);
1 ✔
82
                ensureArraySize(id);
1 ✔
83
                countMap[id] = 1;
1 ✔
84
            } else {
85
                countMap[id]++;
1 ✔
86
            }
87

88
            return id;
1 ✔
89
        } finally {
90
            unlock();
1 ✔
91
        }
92
    }
93

94
    public void add(K k, Element element) {
95
        lock();
1 ✔
96
        try {
97
            int timeIndex = add(k);
1 ✔
98

99
            if (mainIndex != null) {
1 ✔
100
                mainIndex.add(timeIndex, element);
1 ✔
101

102
                if (!viewIndexes.isEmpty()) {
1 ✔
103
                    for (Entry<GraphView, TimeIndexImpl> entry : viewIndexes.entrySet()) {
1 ✔
104
                        GraphViewImpl graphView = (GraphViewImpl) entry.getKey();
1 ✔
105
                        boolean node = element instanceof Node;
1 ✔
106
                        if (node ? graphView.containsNode((Node) element) : graphView.containsEdge((Edge) element)) {
1 ✔
107
                            entry.getValue().add(timeIndex, element);
×
108
                        }
109
                    }
1 ✔
110

111
                }
112
            }
113
        } finally {
114
            unlock();
1 ✔
115
        }
116
    }
1 ✔
117

118
    public void add(TimeMap<K, ?> timeMap) {
119
        for (K timeKey : timeMap.toKeysArray()) {
1 ✔
120
            add(timeKey);
1 ✔
121
        }
122
    }
1 ✔
123

124
    public void add(TimeSet<K> timeSet, Element element) {
125
        for (K timeKey : timeSet.toArray()) {
1 ✔
126
            add(timeKey, element);
1 ✔
127
        }
128
    }
1 ✔
129

130
    protected Integer remove(K k) {
131
        lock();
1 ✔
132
        try {
133
            checkK(k);
1 ✔
134

135
            Integer id = timeSortedMap.get(k);
1 ✔
136
            if (id != null) {
1 ✔
137
                if (--countMap[id] == 0) {
1 ✔
138
                    garbageQueue.add(id);
1 ✔
139
                    timeSortedMap.remove(k);
1 ✔
140
                }
141
            }
142
            return id;
1 ✔
143
        } finally {
144
            unlock();
1 ✔
145
        }
146
    }
147

148
    public void remove(K k, Element element) {
149
        lock();
1 ✔
150
        try {
151
            Integer timeIndex = remove(k);
1 ✔
152
            if (timeIndex == null) {
1 ✔
153
                return;
×
154
            }
155

156
            if (mainIndex != null) {
1 ✔
157
                mainIndex.remove(timeIndex, element);
1 ✔
158

159
                if (!viewIndexes.isEmpty()) {
1 ✔
160
                    for (Entry<GraphView, TimeIndexImpl> entry : viewIndexes.entrySet()) {
1 ✔
161
                        GraphViewImpl graphView = (GraphViewImpl) entry.getKey();
1 ✔
162
                        DirectedSubgraph graph = graphView.getDirectedGraph();
1 ✔
163
                        if (element instanceof Node) {
1 ✔
164
                            if (graph.contains((Node) element)) {
1 ✔
165
                                entry.getValue().remove(timeIndex, element);
1 ✔
166
                            }
167
                        } else if (graph.contains((Edge) element)) {
×
168
                            entry.getValue().remove(timeIndex, element);
×
169
                        }
170
                    }
1 ✔
171
                }
172
            }
173

174
        } finally {
175
            unlock();
1 ✔
176
        }
177
    }
1 ✔
178

179
    public void remove(M timeMap) {
180
        for (K timeKey : timeMap.toKeysArray()) {
1 ✔
181
            remove(timeKey);
1 ✔
182
        }
183
    }
1 ✔
184

185
    public void remove(S timeSet, Element element) {
186
        for (K timeKey : timeSet.toArray()) {
1 ✔
187
            remove(timeKey, element);
1 ✔
188
        }
189
    }
1 ✔
190

191
    public boolean contains(K k) {
192
        checkK(k);
1 ✔
193

194
        lock();
1 ✔
195
        try {
196
            return timeSortedMap.containsKey(k);
1 ✔
197
        } finally {
198
            unlock();
1 ✔
199
        }
200
    }
201

202
    public void index(Element element) {
203
        synchronized (element) {
1 ✔
204
            S timeSet = getTimeSet(element);
1 ✔
205
            lock();
1 ✔
206
            try {
207
                if (timeSet != null) {
1 ✔
208
                    add(timeSet, element);
1 ✔
209
                }
210
                for (Object val : element.getAttributes()) {
1 ✔
211
                    if (val instanceof TimeMap) {
1 ✔
212
                        TimeMap dynamicValue = (TimeMap) val;
1 ✔
213
                        add(dynamicValue);
1 ✔
214
                    }
215
                }
216
            } finally {
217
                unlock();
1 ✔
218
            }
219
        }
1 ✔
220
    }
1 ✔
221

222
    public void clear(Element element) {
223
        synchronized (element) {
1 ✔
224
            S timeSet = getTimeSet(element);
1 ✔
225
            lock();
1 ✔
226
            try {
227
                if (timeSet != null) {
1 ✔
228
                    remove(timeSet, element);
1 ✔
229
                }
230
                for (Object val : element.getAttributes()) {
1 ✔
231
                    if (val instanceof TimeMap) {
1 ✔
232
                        TimeMap dynamicValue = (TimeMap) val;
1 ✔
233
                        remove((M) dynamicValue);
1 ✔
234
                    }
235
                }
236
            } finally {
237
                unlock();
1 ✔
238
            }
239
        }
1 ✔
240
    }
1 ✔
241

242
    public void clear() {
243
        lock();
1 ✔
244
        try {
245
            timeSortedMap.clear();
1 ✔
246
            garbageQueue.clear();
1 ✔
247
            countMap = new int[0];
1 ✔
248
            length = 0;
1 ✔
249

250
            if (mainIndex != null) {
1 ✔
251
                mainIndex.clear();
1 ✔
252

253
                if (!viewIndexes.isEmpty()) {
1 ✔
254
                    for (TimeIndexImpl index : viewIndexes.values()) {
1 ✔
255
                        index.clear();
1 ✔
256
                    }
1 ✔
257
                }
258
            }
259
        } finally {
260
            unlock();
1 ✔
261
        }
262
    }
1 ✔
263

264
    public int size() {
265
        return timeSortedMap.size();
1 ✔
266
    }
267

268
    public TimeIndex getIndex(Graph graph) {
269
        GraphView view = graph.getView();
1 ✔
270
        if (view.isMainView()) {
1 ✔
271
            return mainIndex;
1 ✔
272
        }
273
        if (viewIndexes == null) {
1 ✔
274
            return null;
1 ✔
275
        }
276
        lock();
1 ✔
277
        try {
278
            TimeIndexImpl viewIndex = viewIndexes.get(view);
1 ✔
279
            if (viewIndex != null) {
1 ✔
280
                return viewIndex;
1 ✔
281
            }
282
        } finally {
283
            unlock();
1 ✔
284
        }
285
        // The graph lock is taken first, as indexing the view requires it
286
        graph.readLock();
1 ✔
287
        lock();
1 ✔
288
        try {
289
            TimeIndexImpl viewIndex = viewIndexes.get(view);
1 ✔
290
            if (viewIndex == null) {
1 ✔
291
                // TODO Make the auto-creation optional?
292
                viewIndex = createViewIndex(graph);
1 ✔
293
            }
294
            return viewIndex;
1 ✔
295
        } finally {
296
            unlock();
1 ✔
297
            graph.readUnlock();
1 ✔
298
        }
299
    }
300

301
    protected TimeIndexImpl createViewIndex(Graph graph) {
302
        if (graph.getView().isMainView()) {
1 ✔
303
            throw new IllegalArgumentException("Can't create a view index for the main view");
1 ✔
304
        }
305

306
        TimeIndexImpl viewIndex = createIndex(false);
1 ✔
307
        // TODO: Check view doesn't exist already
308
        viewIndexes.put(graph.getView(), viewIndex);
1 ✔
309

310
        indexView(graph);
1 ✔
311

312
        return viewIndex;
1 ✔
313
    }
314

315
    public void deleteViewIndex(Graph graph) {
316
        if (graph.getView().isMainView()) {
1 ✔
317
            throw new IllegalArgumentException("Can't delete a view index for the main view");
1 ✔
318
        }
319
        lock();
1 ✔
320
        try {
321
            TimeIndexImpl index = viewIndexes.remove(graph.getView());
1 ✔
322
            if (index != null) {
1 ✔
323
                index.clear();
1 ✔
324
            }
325
        } finally {
326
            unlock();
1 ✔
327
        }
328
    }
1 ✔
329

330
    public void indexView(Graph graph) {
331
        TimeIndexImpl viewIndex = viewIndexes.get(graph.getView());
1 ✔
332
        if (viewIndex != null) {
1 ✔
333
            graph.readLock();
1 ✔
334
            lock();
1 ✔
335
            try {
336
                Iterator<T> iterator = null;
1 ✔
337

338
                if (elementType.equals(Node.class)) {
1 ✔
339
                    iterator = (Iterator<T>) graph.getNodes().iterator();
1 ✔
340
                } else if (elementType.equals(Edge.class)) {
1 ✔
341
                    iterator = (Iterator<T>) graph.getEdges().iterator();
1 ✔
342
                }
343

344
                if (iterator != null) {
1 ✔
345
                    while (iterator.hasNext()) {
1 ✔
346
                        Element element = iterator.next();
1 ✔
347
                        S set = getTimeSet(element);
1 ✔
348
                        if (set != null) {
1 ✔
349
                            K[] ts = set.toArray();
1 ✔
350
                            int tsLength = ts.length;
1 ✔
351
                            for (int i = 0; i < tsLength; i++) {
1 ✔
352
                                Integer timestamp = timeSortedMap.get(ts[i]);
1 ✔
353
                                if (timestamp != null) {
1 ✔
354
                                    viewIndex.add(timestamp, element);
1 ✔
355
                                }
356
                            }
357
                        }
358
                    }
1 ✔
359
                }
360
            } finally {
361
                graph.readUnlock();
1 ✔
362
                unlock();
1 ✔
363
            }
364
        }
365
    }
1 ✔
366

367
    public void indexInView(T element, GraphView view) {
368
        TimeIndexImpl viewIndex = viewIndexes.get(view);
1 ✔
369
        if (viewIndex != null) {
1 ✔
370
            lock();
1 ✔
371
            try {
372
                S set = getTimeSet(element);
1 ✔
373
                if (set != null) {
1 ✔
374
                    K[] ts = set.toArray();
1 ✔
375
                    int tsLength = ts.length;
1 ✔
376
                    for (int i = 0; i < tsLength; i++) {
1 ✔
377
                        Integer timestampIndex = timeSortedMap.get(ts[i]);
1 ✔
378
                        if (timestampIndex != null) {
1 ✔
379
                            viewIndex.add(timestampIndex, element);
1 ✔
380
                        }
381
                    }
382
                }
383
            } finally {
384
                unlock();
1 ✔
385
            }
386
        }
387
    }
1 ✔
388

389
    public void clearInView(T element, GraphView view) {
390
        TimeIndexImpl viewIndex = viewIndexes.get(view);
1 ✔
391
        if (viewIndex != null) {
1 ✔
392
            lock();
1 ✔
393
            try {
394
                S set = getTimeSet(element);
1 ✔
395
                if (set != null) {
1 ✔
396
                    K[] ts = set.toArray();
1 ✔
397
                    int tsLength = ts.length;
1 ✔
398
                    for (int i = 0; i < tsLength; i++) {
1 ✔
399
                        Integer timestampIndex = timeSortedMap.get(ts[i]);
1 ✔
400
                        if (timestampIndex != null) {
1 ✔
401
                            viewIndex.remove(timestampIndex, element);
1 ✔
402
                        }
403
                    }
404
                }
405
            } finally {
406
                unlock();
1 ✔
407
            }
408
        }
409
    }
1 ✔
410

411
    public void clear(GraphView view) {
412
        TimeIndexImpl viewIndex = viewIndexes.get(view);
1 ✔
413
        if (viewIndex != null) {
1 ✔
414
            viewIndex.clear();
1 ✔
415
        }
416
    }
1 ✔
417

418
    public boolean hasIndex() {
419
        return mainIndex != null;
1 ✔
420
    }
421

422
    private S getTimeSet(Element element) {
423
        Object[] attributes = element.getAttributes();
1 ✔
424
        if (GraphStoreConfiguration.ENABLE_ELEMENT_TIME_SET && GraphStoreConfiguration.ELEMENT_TIMESET_INDEX < attributes.length) {
1 ✔
425
            return (S) attributes[GraphStoreConfiguration.ELEMENT_TIMESET_INDEX];
1 ✔
426
        }
427
        return null;
×
428
    }
429

430
    private void checkTimeIndex(Integer timeIndex) {
431
        if (timeIndex == null) {
×
432
            throw new IllegalArgumentException("Unknown time index");
×
433
        }
434
    }
×
435

436
    protected void ensureArraySize(int index) {
437
        if (index >= countMap.length) {
1 ✔
438
            int newSize = Math.min(Math
1 ✔
439
                    .max(index + 1, (int) (index * GraphStoreConfiguration.TIMESTAMP_STORE_GROWING_FACTOR)), Integer.MAX_VALUE);
1 ✔
440
            int[] newArray = new int[newSize];
1 ✔
441
            System.arraycopy(countMap, 0, newArray, 0, countMap.length);
1 ✔
442
            countMap = newArray;
1 ✔
443
        }
444
    }
1 ✔
445

446
    public int deepHashCode() {
447
        int hash = 3;
1 ✔
448
        hash = 29 * hash + elementType.hashCode();
1 ✔
449
        for (Map.Entry<K, Integer> entry : timeSortedMap.entrySet()) {
1 ✔
450
            hash = 29 * hash + entry.getKey().hashCode();
1 ✔
451
            hash = 29 * hash + entry.getValue().hashCode();
1 ✔
452
            hash = 29 * hash + countMap[entry.getValue()];
1 ✔
453
        }
1 ✔
454
        return hash;
1 ✔
455
    }
456

457
    public boolean deepEquals(TimeIndexStore obj) {
458
        if (obj == null) {
1 ✔
459
            return false;
1 ✔
460
        }
461
        if (!obj.getClass().equals(getClass())) {
1 ✔
462
            return false;
×
463
        }
464
        TimeIndexStore other = obj;
1 ✔
465
        if (!other.elementType.equals(elementType)) {
1 ✔
466
            return false;
×
467
        }
468
        if (!MapDeepEquals.mapDeepEquals(timeSortedMap, other.timeSortedMap)) {
1 ✔
469
            return false;
1 ✔
470
        }
471
        int[] otherCountMap = other.countMap;
1 ✔
472
        for (Integer k : timeSortedMap.values()) {
1 ✔
473
            if (otherCountMap[k] != countMap[k]) {
1 ✔
474
                return false;
1 ✔
475
            }
476
        }
1 ✔
477
        return true;
1 ✔
478
    }
479

480
    private void lock() {
481
        if (lock != null) {
1 ✔
482
            lock.lock();
1 ✔
483
        }
484
    }
1 ✔
485

486
    private void unlock() {
487
        if (lock != null) {
1 ✔
488
            lock.unlock();
1 ✔
489
        }
490
    }
1 ✔
491
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc