Package ghidra.util.database

# Class DBCachedObjectIndex<K,T extends DBAnnotatedObject>

java.lang.Object
ghidra.util.database.DBCachedObjectIndex<K,T>

Type Parameters:
  `K` - the type of keys in the index, i.e., the indexed field's type
  `T` - the type of objects in the store

public class DBCachedObjectIndex<K,T extends DBAnnotatedObject> extends Object
An index on a field in a `DBCachedObjectStore`

This provides access to a table index backing the store, allowing clients to retrieve objects having specified field values. Its methods are inspired by `NavigableMap`; however, its semantics permit duplicate keys, so this cannot implement it in the manner desired.

Implementation Notes:
  This seems rife for implementing a collection interface, but each defies implementation on our DB framework. Probably because it's better understood as a multimap, which is not a standard Java collection. Guava's proved too burdensome to implement. We never tried Apache's.

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected final DBCachedObjectStoreFactory.DBFieldCodec<K,T,?>`
  `codec`
  `protected final int`
  `columnIndex`
  `protected final DirectedIterator.Direction`
  `direction`
  `protected final ErrorHandler`
  `errHandler`
  `protected final FieldSpan`
  `fieldSpan`
  `protected final DBCachedObjectStore<T>`
  `store`

- ## Constructor Summary

  Constructors
  Modifier
  Constructor
  Description
  `protected`
  `DBCachedObjectIndex(DBCachedObjectStore<T> store, ErrorHandler errHandler, DBCachedObjectStoreFactory.DBFieldCodec<K,T,?> codec, int columnIndex, FieldSpan fieldSpan, DirectedIterator.Direction direction)`
  Construct an index

- ## Method Summary

  Modifier and Type
  Method
  Description
  `Map.Entry<K,T>`
  `ceilingEntry(K key)`
  Get the entry at or after the given key
  `K`
  `ceilingKey(K key)`
  Get the key at or after the given key
  `T`
  `ceilingValue(K key)`
  Get the value at or after the given key
  `protected boolean`
  `containsKey(Field encoded)`
  `boolean`
  `containsKey(K key)`
  Check if there is any object having the given value for its indexed field
  `boolean`
  `containsValue(T value)`
  Check if the given object is in the index
  `protected int`
  `countKey(Field encoded)`
  `int`
  `countKey(K key)`
  Count the number of objects whose indexed field has the given value
  `DBCachedObjectIndex<K,T>`
  `descending()`
  Get a reversed view of this index
  `Iterable<Map.Entry<K,T>>`
  `entries()`
  Iterate over the entries as ordered by the index
  `Map.Entry<K,T>`
  `firstEntry()`
  Get the first entry in the index
  `K`
  `firstKey()`
  Get the first key in the index
  `protected static <T> T`
  `firstOf(Iterable<T> of)`
  `T`
  `firstValue()`
  Get the first object in the index
  `Map.Entry<K,T>`
  `floorEntry(K key)`
  Get the entry at or before the given key
  `K`
  `floorKey(K key)`
  Get the key at or before the given key
  `T`
  `floorValue(K key)`
  Get the value at or before the given key
  `protected Collection<T>`
  `get(Field encoded)`
  `Collection<T>`
  `get(K key)`
  Get the objects having the given value in the indexed field
  `Collection<T>`
  `getLazily(K key)`
  Get the objects having the given value in the index field
  `T`
  `getOne(K value)`
  Get a unique object having the given value in the index field
  `DBCachedObjectIndex<K,T>`
  `head(K to, boolean toInclusive)`
  Get a sub-ranged view of this index, limited to entries whose keys occur before the given key
  `Map.Entry<K,T>`
  `higherEntry(K key)`
  Get the entry after the given key
  `K`
  `higherKey(K key)`
  Get the key after the given key
  `T`
  `higherValue(K key)`
  Get the value after the given key
  `boolean`
  `isEmpty()`
  Check if this index is empty
  `Iterable<K>`
  `keys()`
  Iterate over the values of the indexed column, in order
  `Map.Entry<K,T>`
  `lastEntry()`
  Get the last entry in the index
  `K`
  `lastKey()`
  Get the last key in the index
  `T`
  `lastValue()`
  Get the last object in the index
  `Map.Entry<K,T>`
  `lowerEntry(K key)`
  Get the entry before the given key
  `K`
  `lowerKey(K key)`
  Get the key before the given key
  `T`
  `lowerValue(K key)`
  Get the value before the given key
  `DBCachedObjectIndex<K,T>`
  `sub(K from, boolean fromInclusive, K to, boolean toInclusive)`
  Get a sub-ranged view of this index
  `DBCachedObjectIndex<K,T>`
  `tail(K from, boolean fromInclusive)`
  Get a sub-ranged view of this index, limited to entries whose keys occur after the given key
  `Iterable<T>`
  `values()`
  Iterate over the objects as ordered by the index

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### store

    protected final DBCachedObjectStore<T extends DBAnnotatedObject> store

  - ### errHandler

    protected final ErrorHandler errHandler

  - ### codec

    protected final DBCachedObjectStoreFactory.DBFieldCodec<K,T extends DBAnnotatedObject,?> codec

  - ### columnIndex

    protected final int columnIndex

  - ### fieldSpan

    protected final FieldSpan fieldSpan

  - ### direction

    protected final DirectedIterator.Direction direction

- ## Constructor Details

  - ### DBCachedObjectIndex

    protected DBCachedObjectIndex(DBCachedObjectStore<T> store, ErrorHandler errHandler, DBCachedObjectStoreFactory.DBFieldCodec<K,T,?> codec, int columnIndex, FieldSpan fieldSpan, DirectedIterator.Direction direction)
    Construct an index

    Clients should use `DBCachedObjectStore.getIndex(Class, DBObjectColumn)`.

    Parameters:
      `store` - the store containing the indexed objects
      `errHandler` - an error handler
      `codec` - the codec for the indexed field/column
      `columnIndex` - the column number
      `fieldSpan` - required: the restricted range, can be `FieldSpan.ALL`
      `direction` - the sort order / direction of iteration

- ## Method Details

  - ### get

    protected Collection<T> get(Field encoded)

  - ### get

    public Collection<T> get(K key)
    Get the objects having the given value in the indexed field

    NOTE: The objects' primary keys are retrieved immediately, but the returned collection loads each requested object lazily. This may have timing implications. If the returned collection is used at a later time, the keys found may no longer be valid, and even if they are, the indexed field may no longer have the requested value when retrieved. See `getLazily(Object)`.

    Parameters:
      `key` - the value
    Returns:
      the collection of objects

  - ### getLazily

    public Collection<T> getLazily(K key)
    Get the objects having the given value in the index field

    This differs from `get(Object)` in that the keys are retrieved each time the collection is iterated. The returned collection can be saved and used later. The iterator itself still has a fixed set of keys, though, so clients should use it and discard it in a timely fashion, and/or while holding the domain object's lock.

    Parameters:
      `key` - the value
    Returns:
      the lazy collection of objects

  - ### getOne

    public T getOne(K value)
    Get a unique object having the given value in the index field

    Clients should use this method when the index behaves like a map, rather than a multimap. It is the client's responsibility to ensure that duplicate values do not exist in the indexed column.

    Parameters:
      `value` - the value
    Returns:
      the object, if found, or null
    Throws:
      `IllegalStateException` - if the object is not unique

  - ### keys

    public Iterable<K> keys()
    Iterate over the values of the indexed column, in order

    Despite being called keys, the values may not be unique

    Returns:
      the iterator

  - ### values

    public Iterable<T> values()
    Iterate over the objects as ordered by the index
    Returns:
      the iterator

  - ### entries

    public Iterable<Map.Entry<K,T>> entries()
    Iterate over the entries as ordered by the index

    Each entry is a key-value value where the "key" is the value of the indexed field, and the "value" is the object.

    Returns:
      the iterator

  - ### firstOf

    protected static <T> T firstOf(Iterable<T> of)

  - ### isEmpty

    public boolean isEmpty()
    Check if this index is empty

    Except for sub-ranged indexes, this is equivalent to checking if the object store is empty. For sub-ranged indexes, this checks if the store contains any object whose value for the indexed field falls within the restricted range.

    Returns:
      true if empty

  - ### containsKey

    protected boolean containsKey(Field encoded)

  - ### containsKey

    public boolean containsKey(K key)
    Check if there is any object having the given value for its indexed field

    This method is more efficient than using `get(key).isEmpty()`, since it need only find one match, whereas `get(Object)` will retrieve every match. Granted, it doesn't make sense to immediately call `get(Object)` after `containsKey(Object)` returns true.

  - ### containsValue

    public boolean containsValue(T value)
    Check if the given object is in the index

    Except for sub-ranged indexes, this is equivalent to checking if the object is in the store. For a sub-ranged index, the value of its indexed field must fall within the restricted range.

    Parameters:
      `value` - the object
    Returns:
      true if it appears in this (sub-ranged) index.

  - ### countKey

    protected int countKey(Field encoded)

  - ### countKey

    public int countKey(K key)
    Count the number of objects whose indexed field has the given value
    Parameters:
      `key` - the value
    Returns:
      the count

  - ### firstKey

    public K firstKey()
    Get the first key in the index
    Returns:
      the first key, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### firstValue

    public T firstValue()
    Get the first object in the index
    Returns:
      the first object, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### firstEntry

    public Map.Entry<K,T> firstEntry()
    Get the first entry in the index
    Returns:
      the first key, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### lastKey

    public K lastKey()
    Get the last key in the index
    Returns:
      the first key, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### lastValue

    public T lastValue()
    Get the last object in the index
    Returns:
      the first object, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### lastEntry

    public Map.Entry<K,T> lastEntry()
    Get the last entry in the index
    Returns:
      the first key, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### lowerKey

    public K lowerKey(K key)
    Get the key before the given key
    Parameters:
      `key` - the key
    Returns:
      the previous key, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### lowerValue

    public T lowerValue(K key)
    Get the value before the given key
    Parameters:
      `key` - the key
    Returns:
      the value of the previous key, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### lowerEntry

    public Map.Entry<K,T> lowerEntry(K key)
    Get the entry before the given key
    Parameters:
      `key` - the key
    Returns:
      the entry of the previous key, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### floorKey

    public K floorKey(K key)
    Get the key at or before the given key
    Parameters:
      `key` - the key
    Returns:
      the same or previous key, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### floorValue

    public T floorValue(K key)
    Get the value at or before the given key
    Parameters:
      `key` - the key
    Returns:
      the value of the same or previous key, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### floorEntry

    public Map.Entry<K,T> floorEntry(K key)
    Get the entry at or before the given key
    Parameters:
      `key` - the key
    Returns:
      the entry of the same or previous key, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### ceilingKey

    public K ceilingKey(K key)
    Get the key at or after the given key
    Parameters:
      `key` - the key
    Returns:
      the same or next key, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### ceilingValue

    public T ceilingValue(K key)
    Get the value at or after the given key
    Parameters:
      `key` - the key
    Returns:
      the value of the same or next key, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### ceilingEntry

    public Map.Entry<K,T> ceilingEntry(K key)
    Get the entry at or after the given key
    Parameters:
      `key` - the key
    Returns:
      the entry of the same or next key, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### higherKey

    public K higherKey(K key)
    Get the key after the given key
    Parameters:
      `key` - the key
    Returns:
      the same or next key, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### higherValue

    public T higherValue(K key)
    Get the value after the given key
    Parameters:
      `key` - the key
    Returns:
      the value of the next key, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### higherEntry

    public Map.Entry<K,T> higherEntry(K key)
    Get the entry after the given key
    Parameters:
      `key` - the key
    Returns:
      the entry of the next key, or null
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### head

    public DBCachedObjectIndex<K,T> head(K to, boolean toInclusive)
    Get a sub-ranged view of this index, limited to entries whose keys occur before the given key
    Parameters:
      `to` - the upper bound
      `toInclusive` - whether the upper bound is included in the restricted view
    Returns:
      the restricted view
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### tail

    public DBCachedObjectIndex<K,T> tail(K from, boolean fromInclusive)
    Get a sub-ranged view of this index, limited to entries whose keys occur after the given key
    Parameters:
      `from` - the lower bound
      `fromInclusive` - whether the lower bound is included in the restricted view
    Returns:
      the restricted view
    See Also:
      - `descending()`
      - `sub(Object, boolean, Object, boolean)`

  - ### sub

    public DBCachedObjectIndex<K,T> sub(K from, boolean fromInclusive, K to, boolean toInclusive)
    Get a sub-ranged view of this index
    Parameters:
      `from` - the lower bound
      `fromInclusive` - whether the lower bound is included in the restricted view
      `to` - the upper bound
      `toInclusive` - whether the upper bound is included in the restricted view
    Returns:
      the restricted view
    See Also:
      - `descending()`

  - ### descending

    public DBCachedObjectIndex<K,T> descending()
    Get a reversed view of this index

    This affects iteration as well as all the navigation and sub-ranging methods. E.g., `lowerKey(Object)` in the reversed view will behave like `higherKey(Object)` in the original. In other words, the returned index is equivalent to the original, but with a negated comparator. Calling `descending()` on the returned view will return a view equivalent to the original.

    Returns:
      the reversed view