add explicit event list

This commit is contained in:
2021-02-27 12:26:07 +00:00
parent c41dd646da
commit 68918689e7
18 changed files with 560 additions and 184 deletions

View File

@ -10,3 +10,4 @@ Export-Package: com.minres.scviewer.database,
Bundle-ActivationPolicy: lazy
Service-Component: OSGI-INF/component.xml,OSGI-INF/component2.xml
Automatic-Module-Name: com.minres.scviewer.database
Require-Bundle: org.eclipse.collections;bundle-version="10.4.0"

View File

@ -0,0 +1,28 @@
package com.minres.scviewer.database;
public class EventEntry implements Comparable<EventEntry>{
public long timestamp; // unsigned
public IEvent[] events = null;
public EventEntry(long timestamp) {
this.timestamp = timestamp;
}
public EventEntry(long timestamp, IEvent[] events) {
this.timestamp = timestamp;
this.events = events;
}
@Override
public int compareTo(EventEntry o) {
return Long.compareUnsigned(timestamp, o.timestamp);
}
@Override
public String toString() {
return String.format("e.%d@%d", events.length,timestamp);
}
}

View File

@ -1,100 +1,196 @@
package com.minres.scviewer.database;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.TreeMap;
import java.util.Collections;
public class EventList<K,V> implements IEventList<K,V>{
public class EventList implements IEventList {
NavigableMap<K,V> backing ;
ArrayList<EventEntry> store = new ArrayList<>();
int start = 0;
int end = store.size();
boolean unmodifiable = false;
public class Iterator implements java.util.Iterator<EventEntry> {
EventList list;
private int pos;
public Iterator(EventList list) {
this.list=list;
this.pos=-1;
}
@Override
public boolean hasNext() {
return pos<(list.end-1);
}
@Override
public EventEntry next() {
if(hasNext()) {
pos++;
return list.store.get(pos);
} else
return null;
}
@Override
public void remove() {
list.store.remove(pos);
}
}
public EventList() {
backing=new TreeMap<>();
}
public EventList(NavigableMap<K, V> subMap) {
backing=subMap;
private EventList(ArrayList<EventEntry> store , int start, int end) {
this.store=store;
this.start=start;
this.end=end;
this.unmodifiable=true;
}
@Override
public Entry<K, V> floorEntry(K key) {
return backing.floorEntry(key);
public IEventList subMap(long from, boolean includeFrom, long to) {
//the index of the first element greater than the key, or list.size()
int beginIndex = Collections.binarySearch(store, new EventEntry(from));
int startIndex = beginIndex < 0? -(beginIndex + 1): beginIndex;
int endIndex = Collections.binarySearch(store, new EventEntry(to));
endIndex = endIndex < 0? -(endIndex + 1): endIndex+1;
if(beginIndex>0 && !includeFrom)
return new EventList(store, startIndex+1, endIndex);
else
return new EventList(store, startIndex, endIndex);
}
@Override
public Entry<K, V> ceilingEntry(K key) {
return backing.ceilingEntry(key);
}
@Override
public Entry<K, V> firstEntry() {
return backing.firstEntry();
}
@Override
public Entry<K, V> lastEntry() {
return backing.lastEntry();
}
@Override
public V get(K key) {
return backing.get(key);
}
@Override
public Entry<K, V> higherEntry(K key) {
return backing.higherEntry(key);
}
@Override
public Entry<K, V> lowerEntry(K key) {
return backing.lowerEntry(key);
}
@Override
public IEventList<K, V> subMap(K key, boolean b, K key2, boolean c) {
return new EventList<K,V>( backing.subMap(key, b, key2, c));
}
@Override
public int size() {
return backing.size();
return end-start;
}
@Override
public Collection<K> keys() {
return backing.keySet();
public boolean containsKey(long key) {
int index = Collections.binarySearch(store, new EventEntry(key));
return index>=0 && index>=start && index<end;
}
@Override
public Collection<V> values() {
return backing.values();
public IEvent[] get(long key) {
int index = Collections.binarySearch(store, new EventEntry(key));
if(index<0) return null;
return index>=start && index<end? store.get(index).events: null;
}
@Override
public boolean containsKey(K key) {
return backing.containsKey(key);
public IEvent[] put(long key, IEvent[] value) {
if(unmodifiable) throw new UnsupportedOperationException();
EventEntry e = new EventEntry(key, value);
if(store.size()==0 || store.get(store.size()-1).timestamp < key) {
store.add(e);
} else {
int index = Collections.binarySearch(store, new EventEntry(key));
// < 0 if element is not in the list, see Collections.binarySearch
if (index < 0) {
index = -(index + 1);
store.add(index, e);
} else {
// Insertion index is index of existing element, to add new element behind it increase index
store.set(index, e);
}
}
end=store.size();
return e.events;
}
@Override
public V put(K key, V value) {
return backing.put(key, value);
}
@Override
public Collection<Entry<K, V>> entrySet() {
return backing.entrySet();
public Collection<EventEntry> entrySet() {
if(start != 0 || end != store.size())
return Collections.unmodifiableList(store.subList(start, end));
else
return Collections.unmodifiableList(store);
}
@Override
public boolean isEmpty() {
return backing.isEmpty();
return start==end || store.isEmpty();
}
@Override
public K lastKey() {
return backing.lastKey();
public long firstKey() {
return store.get(start).timestamp;
}
@Override
public long lastKey() {
return store.get(end-1).timestamp;
}
// Navigable map functions
@Override
public EventEntry firstEntry() {
return store.get(start);
}
@Override
public EventEntry lastEntry() {
return store.get(end-1);
}
@Override
public EventEntry floorEntry(long key) {
int index = Collections.binarySearch(store, new EventEntry(key));
if(index==-1) return null;
// < 0 if element is not in the list, see Collections.binarySearch
if (index < 0) {
index = -(index + 2);
}
if(index>=end)
return store.get(end-1);
return index<start? null: store.get(index);
}
@Override
public EventEntry ceilingEntry(long key) {
int index = Collections.binarySearch(store, new EventEntry(key));
// < 0 if element is not in the list, see Collections.binarySearch
if (index < 0)
index = -(index + 1);
if(index<start)
return store.get(start);
return index>=end? null: store.get(index);
}
@Override
public EventEntry lowerEntry(long key) {
int index = Collections.binarySearch(store, new EventEntry(key));
// < 0 if element is not in the list, see Collections.binarySearch
if (index < 0)
index = -(index + 1);
index--;
if(index>=end)
return store.get(end-1);
return index>=end || index<start ?null:store.get(index);
}
@Override
public EventEntry higherEntry(long key) {
int index = Collections.binarySearch(store, new EventEntry(key));
// < 0 if element is not in the list, see Collections.binarySearch
if (index < 0)
index = -(index + 1);
else
index++;
if(index<start)
return store.get(start);
return index>=end || index<start ?null:store.get(index);
}
@Override
public java.util.Iterator<EventEntry> iterator() {
return new Iterator(this);
}
}

View File

@ -1,40 +1,84 @@
package com.minres.scviewer.database;
import java.util.Collection;
import java.util.Map.Entry;
public interface IEventList<K,V> {
Entry<K, V> floorEntry(K key);
Entry<K, V> ceilingEntry(K key);
Entry<K, V> firstEntry();
Entry<K, V> lastEntry();
V get(K key);
Entry<K, V> higherEntry(K key);
Entry<K, V> lowerEntry(K key);
IEventList<K, V> subMap(K key, boolean b, K key2, boolean c);
public interface IEventList extends Iterable<EventEntry> {
int size();
Collection<K> keys();
Collection<V> values();
Collection<EventEntry> entrySet();
boolean containsKey(K key);
boolean containsKey(long key);
V put(K key, V value);
IEvent[] get(long key);
Collection<Entry<K, V>> entrySet();
IEvent[] put(long key, IEvent[] value);
long firstKey();
long lastKey();
boolean isEmpty();
K lastKey();
/**
* Returns a key-value mapping associated with the greatest key less
* than or equal to the given key, or null if there is no such key.
*
* @param key
* @return
*/
EventEntry floorEntry(long key);
/**
* Returns a key-value mapping associated with the least key greater
* than or equal to the given key, or null if there is no such key.
*
* @param key
* @return
*/
EventEntry ceilingEntry(long key);
/**
* Returns a key-value mapping associated with the least key in this map,
* or null if the map is empty.
*
* @return
*/
EventEntry firstEntry();
/**
* Returns a key-value mapping associated with the least key in this map,
* or null if the map is empty.
*
* @return
*/
EventEntry lastEntry();
/**
* Returns a key-value mapping associated with the least key strictly greater
* than the given key, or null if there is no such key.
*
* @param key
* @return
*/
EventEntry higherEntry(long key);
/**
* Returns a key-value mapping associated with the greatest key strictly less
* than the given key, or null if there is no such key.
*
* @param key
* @return
*/
EventEntry lowerEntry(long key);
/**
* Returns a view of the portion of this map whose keys range from
* {@code fromKey} to {@code toKey}. If {@code fromKey} and
* {@code toKey} are equal, the returned map is empty unless
* {@code fromInclusive} is true. The
* returned map is backed by this map, so changes in the returned map are
* reflected in this map, and vice-versa. The returned map supports all
* optional map operations that this map supports.
*
* @param fromKey low endpoint of the keys in the returned map
* @param fromInclusive {@code true} if the low endpoint
* is to be included in the returned view
* @param toKey high endpoint of the keys in the returned map (inclusive)
*/
IEventList subMap(long key, boolean b, long key2);
}

View File

@ -39,7 +39,7 @@ public interface IWaveform extends IHierNode {
*
* @return the events
*/
public IEventList<Long, IEvent[]> getEvents();
public IEventList getEvents();
/**
* Gets the events at time.