K
- Dictionary key typeV
- Dictionary value typepublic class ScopedDictionary<K,V>
extends java.lang.Object
Object
key and an optional, user-defined
object that can store arbitrary user data. As a result of the lookup
process, if an entry is found, the user-defined object is returned.
When entries are added, they are stored in a flat list called a scope.
Each scope can store a set of entries where each symbol key must be unique.
The user has control over how many scopes exist. By default, no scopes
are available. The user of this class is responsible for adding scopes
using the addScope
method. When the entries stored in the
current scope should no longer be available, the scope can be removed
using the deleteScope
method. This multilevel scope
approach can be thought of as a stack of scopes where the current scope
is the top of the stack and the bottom of the stack has a special scope
that is considered "global". Entries can be added to the current scope
or to the global scope using the addEntry
method.
Since the global scope has a special meaning, a convenience constructor is provided that automatically creates the global scope.
Keys must only be unique within a single scope. If the same key exists
in multiple scopes, the instance found closest to the current scope (top
of stack) is the one that is found on lookup. Likewise, when an entry
is deleted using deleteEntry
, the topmost entry is the one
removed.
Modifier and Type | Class and Description |
---|---|
protected static class |
ScopedDictionary.Node<K,V>
Represents complex items on the stack of scopes.
|
Modifier and Type | Field and Description |
---|---|
private java.util.LinkedList<ScopedDictionary.Node<K,V>> |
scopes
Implements stackable scopes
|
Constructor and Description |
---|
ScopedDictionary()
Default constructor.
|
ScopedDictionary(java.lang.Object extra)
Convenience constructor that automatically creates the global scope.
|
Modifier and Type | Method and Description |
---|---|
boolean |
addEntry(boolean global,
K key,
V value)
Adds a value to the current or global scope or replaces its
user-defined object.
|
boolean |
addEntryAt(int depth,
K key,
V value)
Adds a value to the scope at the specified depth or replaces its user-defined object.
|
void |
addScope(java.lang.Object extra)
Creates a new scope and associates a user-defined object with it.
|
void |
apply(K key,
java.util.function.Function<java.util.Map<K,V>,java.lang.Boolean> code)
Execute the given code for all values, in all scopes, for the specified key.
|
void |
clear()
Removes all entries from all scopes in the stack, top scope first.
|
void |
copyAll(ScopedDictionary<K,V> source,
boolean keepGlobal)
Clear this dictionary and copy all content from the source.
|
boolean |
deleteEntry(K key)
Searches all scopes from the top of the stack down and deletes
the first found occurrence of the target entry.
|
void |
deleteScope()
Deletes the current scope which is the one on the top of the stack.
|
void |
deleteScope(boolean propagate)
Deletes the current scope which is the one on the top of the stack, and
optionally propagates all entries defined in that scope to the next
scope on the stack.
|
void |
dump()
Prints a report of all entries found by scope, starting at the bottom
of the stack (of scopes) working toward the top.
|
void |
dump(java.io.PrintStream output)
Prints a report of all entries found by scope, starting at the bottom
of the stack (of scopes) working toward the top.
|
void |
dump(java.io.PrintWriter output)
Prints a report of all entries found by scope, starting at the bottom
of the stack (of scopes) working toward the top.
|
void |
dumpCurrentScope(java.lang.String text,
java.io.PrintStream output)
Prints a report of all entries found in the current scope.
|
void |
dumpCurrentScope(java.lang.String text,
java.io.PrintWriter output)
Prints a report of all entries found in the current scope.
|
private void |
dumpScope(ScopedDictionary.Node<K,V> n,
int depth,
java.lang.String text,
java.io.PrintWriter output)
Prints a report of all entries found in a given scope.
|
java.util.Set<java.util.Map.Entry<K,V>> |
entrySet()
Returns a set containing all defined entries (as
Map.Entry
objects). |
java.util.Set<java.util.Map.Entry<K,V>> |
entrySet(int scope)
Returns a set containing all defined entries (as
Map.Entry
objects) in the scope specified. |
java.util.Map<K,V> |
getDictionaryAtScope(int scope,
boolean create)
Returns the dictionary from the scope specified, or
null if
the specified scope does not exist. |
java.lang.Object |
getScope()
Accesses the user object in the current scope.
|
java.lang.Object |
getScopeAt(int scope)
Accesses the user object in the scope specified.
|
V |
getValueAtScope(K key,
int scope)
Gets the value for the given key in the scope specified.
|
java.util.Set<K> |
keySet()
Returns a set containing all defined keys.
|
java.util.Set<K> |
keySet(int scope)
Returns a set containing all defined keys in the scope specified.
|
int |
locate(K key)
Searches all scopes from the top of the stack down for a given entry.
|
int |
locate(K key,
V value)
Searches all scopes from the top of the stack down for the specified
key and value pair and returns 0-based index of the depth where
that pair is found.
|
V |
lookup(K key)
Searches all scopes from the top of the stack down for a given entry.
|
V |
lookup(K key,
int fromScope)
Searches all scopes from the specified scope in the stack down for a given entry.
|
K |
processKey(K key)
Subclasses which need to process the dictionary lookup key before it is
used must override this method.
|
boolean |
removeEntryAtScope(K key,
int scope)
Remove the entry with the specified key from the scope specified.
|
int |
removeEntryThroughScope(K key,
int scope)
Remove the entry with the specified key from all scopes up to and including the scope
specified.
|
V |
reverseLookup(K key)
Searches all scopes bottom up, starting from the global to the innermost scope.
|
V |
reverseLookup(K key,
int scope)
Searches all scopes bottom up, starting from the specified scope to the innermost scope.
|
void |
setScope(java.lang.Object extra)
Replaces the user object in the current scope.
|
void |
setScopeAt(int scope,
java.lang.Object extra)
Replaces the user object in the scope specified.
|
boolean |
setValueAtScope(K key,
int scope,
V value)
Sets specified value within the entry in the scope specified.
|
int |
size()
Returns the stack depth.
|
java.util.Collection<V> |
values()
Returns an unmodifiable collection view of all defined values.
|
java.util.Collection<V> |
values(int scope)
Returns a collection containing all defined values in the scope
specified.
|
private java.util.LinkedList<ScopedDictionary.Node<K,V>> scopes
public ScopedDictionary()
public ScopedDictionary(java.lang.Object extra)
extra
- Object to be associated with the global scope.public void copyAll(ScopedDictionary<K,V> source, boolean keepGlobal)
source
- The source dictionary.keepGlobal
- When true
, the global dictionary is exposed directly to this copy;
otherwise is duplicated.public void addScope(java.lang.Object extra)
extra
- Object to be associated with new scope.public void deleteScope()
public void deleteScope(boolean propagate)
propagate
- true
to propagate entries up to the next scope;
false
to simply remove those entries.public java.lang.Object getScope()
public void setScope(java.lang.Object extra)
extra
- Any object that will be associated with this scope.public java.lang.Object getScopeAt(int scope)
scope
- The depth (in number of scopes from the top of the stack) from
which the value must be gotten. Use -1 to reference the global
scope.public void setScopeAt(int scope, java.lang.Object extra)
scope
- The depth (in number of scopes from the top of the stack) from
which the value must be gotten. Use -1 to reference the global
scope.extra
- Any object that will be associated with this scope.public int size()
public boolean addEntry(boolean global, K key, V value)
global
- Specifies the target scope. false
specifies the
current scope, and true
specifies the global
scope.key
- The lookup key.value
- The stored value which may be any object.true
if the entry has been added,
false
if its value has been replaced.public boolean addEntryAt(int depth, K key, V value) throws java.lang.ArrayIndexOutOfBoundsException
depth
- zero-based index of the target scope, starting from the outermost scope.key
- The lookup key.value
- The stored value which may be any object.true
if the entry has been added,
false
if its value has been replaced.java.lang.ArrayIndexOutOfBoundsException
- if invalid depth
is specified.public boolean deleteEntry(K key)
key
- The lookup key.true
if the entry has been deleted.public void clear()
public int locate(K key, V value)
key
- The lookup key.value
- The value to search.public java.util.Map<K,V> getDictionaryAtScope(int scope, boolean create)
null
if
the specified scope does not exist.scope
- The depth (in number of scopes from the top of the stack) at
which the value must be set.create
- true
to create a dictionary for this scope if one
does not already exist; false
to have an empty
(immutable) dictionary returned if one does not already exist.create
is set to
false
. If the scope itself does not exist, then
null
is returned.public int removeEntryThroughScope(K key, int scope)
key
- The lookup key.scope
- The depth (in number of scopes from the top of the stack) from which the entry
is to be removed. It will be removed from every scope in which it exists, up to
and including this depth.0
if it was not
found.public boolean removeEntryAtScope(K key, int scope)
key
- The lookup key.scope
- The depth (in number of scopes from the top of the stack) from
which the entry is to be removed.true
if the value was removed set, or
false
if it was not found.public boolean setValueAtScope(K key, int scope, V value)
key
- The lookup key.scope
- The depth (in number of scopes from the top of the stack) at
which the value must be set.value
- The replacement value.true
if the value was successfully set, or
false
if any error occurred.public V getValueAtScope(K key, int scope)
key
- The lookup key.scope
- The depth (in number of scopes from the top of the stack) from
which the value must be gotten. Use -1 to reference the global
scope.null
if no such name exists.public void apply(K key, java.util.function.Function<java.util.Map<K,V>,java.lang.Boolean> code)
This will walk all dictionaries, from the innermost scope to the global scope. If a dictionary mapping doesn't exist in a certain scope for this key, that scope will not be processed.
The scope processing will continue until the caller (via the code function) decides to terminate the processing.
key
- The key which needs to have its values processed.code
- The code to be applied to each dictionary, for the given key. If this function
returns true, the search will end.public V lookup(K key)
key
- The lookup key.null
if not found.public V lookup(K key, int fromScope)
key
- The lookup key.fromScope
- The 1-based index from which to start the backwards walk of scopes to be searched.
For instance, to search the full dictionary, the size of the dictionary should be
passed for this parameter; to search only the bottom scope, 1 should be passed.null
if not found.public V reverseLookup(K key)
key
- The lookup key.null
if not found.public V reverseLookup(K key, int scope)
key
- The lookup key.scope
- The 0-based scope at which to start the reverse lookup. Must be in the range
(scope >= 0 && scope < size())
.null
if not found.java.lang.IndexOutOfBoundsException
- if scope
is outside of the permitted range.public int locate(K key)
key
- The lookup key.public java.util.Set<K> keySet()
public java.util.Set<K> keySet(int scope)
scope
- The depth (in number of scopes from the top of the stack) from
which the keys are collected. Use -1 to reference the global
scope.public java.util.Set<java.util.Map.Entry<K,V>> entrySet()
Map.Entry
objects).public java.util.Set<java.util.Map.Entry<K,V>> entrySet(int scope)
Map.Entry
objects) in the scope specified.scope
- The depth (in number of scopes from the top of the stack) from
which the entries are collected. Use -1 to reference the global
scope.public java.util.Collection<V> values()
public java.util.Collection<V> values(int scope)
scope
- The depth (in number of scopes from the top of the stack) from
which the values are collected. Use -1 to reference the global
scope.public void dump(java.io.PrintStream output)
output
- PrintStream
object to which to dump.public void dump(java.io.PrintWriter output)
output
- PrintWriter
object to which to dump.public void dumpCurrentScope(java.lang.String text, java.io.PrintStream output)
text
- Additional text to print.output
- PrintStream
object to which to dump.public void dumpCurrentScope(java.lang.String text, java.io.PrintWriter output)
text
- Additional text to print.output
- PrintWriter
object to which to dump.public void dump()
System.err
stream for output.public K processKey(K key)
key
argument unchanged.key
- The lookup key.key
argument.private void dumpScope(ScopedDictionary.Node<K,V> n, int depth, java.lang.String text, java.io.PrintWriter output)
n
- The Node
instance to dump.depth
- The indent level.text
- Additional text to print.output
- PrintWriter
object to which to dump.