public interface SectionInfo
The section manager provides three main functions:
get(Key). Their availability can be checked via isCached(Key).get(Key), if the requested key is not
yet cached.startTransaction(Key)). Then the result value is
stored in the section manager by ending the transaction (see
endTransaction(Key, Object, Collection)). If any problems occur during the computation,
the transaction is cancelled (see cancelTransaction(Key)).The information is stored in the section manager by using keys, which are a pair of name and value type. The section specific information should be identified by the section name, which should be unique.
get(Key),
startTransaction(Key),
endTransaction(Key, Object, Collection),
cancelTransaction(Key),
The default section manager implementation| Modifier and Type | Method and Description |
|---|---|
Set<Key<?>> |
cancelTransaction(Key<?> key)
Cancels the ongoing transaction in the section manager.
|
<T> void |
endTransaction(Key<T> key,
T value)
This is a convenience method for
endTransaction(Key, Object, Collection), with no
explicit dependencies. |
<T> void |
endTransaction(Key<T> key,
T value,
Collection<? extends Key<?>> explicitDependencies)
Ends the transaction for the given key and associates the computed value to this key in the
section manager cache.
|
void |
ensureTransaction(Key<?> key)
Ensures that the indicated transaction is active in the section manager.
|
<T> T |
get(Key<T> key)
Looks up and resolves the
key in the section manager. |
Key<?> |
getCurrentTransaction()
Retrieves the currently active transaction.
|
Set<Key<?>> |
getDependants(Key<?> key)
Retrieves keys of all elements that depend on the given
key. |
Set<Key<?>> |
getDependencies(Key<?> key)
Retrieves keys of all elements, that the given
key depends on. |
Dialect |
getDialect()
Returns the current language extension dialect is being managed (see
Dialect). |
Level |
getTracingLevel()
Get current section manager tracing level as set by
setTracing(boolean, Level). |
boolean |
isCached(Key<?> key)
Checks whether the given key is cached within the section information manager
|
boolean |
isTracing()
Returns whether debugging tracing is on or not as set by
setTracing(boolean, Level). |
<T> Set<Key<? extends T>> |
keysOf(Class<T> clsName)
Retrieve all the keys involving a given class type
|
Set<Key<?>> |
keysOf(String name)
Retrieve all the keys involving a given name (e.g., ZSect, Spec, Source, etc for given string name)
|
void |
postponeTransaction(Key<?> postponedKey,
Key<?> nextKey)
Postpones the just-started transaction to ensure a correct transaction order.
|
<T> void |
put(Key<T> key,
T value)
This is a convenience method for
put(Key, Object, Collection), with no explicit
dependencies. |
<T> void |
put(Key<T> key,
T value,
Collection<? extends Key<?>> explicitDependencies)
Adds the value to the section manager cache.
|
boolean |
removeKey(Key<?> key)
Removes the key and its value from the section manager cache.
|
void |
reset()
Resets the section manager.
|
<T> Key<? super T> |
retrieveKey(T value)
Returns whether the given value has already been computed and is cached.
|
boolean |
setTracing(boolean on,
Level level)
Set section management tracing on/off.
|
void |
startTransaction(Key<?> key)
Starts a section manager transaction.
|
<T> T get(Key<T> key) throws CommandException, SectionInfoException
key in the section manager. It never returns null. If
a key is present in the section manager (i.e., isCached(Key)= true), the
cached value is returned. Otherwise, a command must be present in the section manager for the
indicated key type. It is used to compute the result for the given key and store in the section
manager. This value is returned after computation. If any problems during the process occur,
the CommandException is thrown.
The commands for different result types are configured dynamically in the section manager. See
SectionManager.get(Key) for details about some core commands and their keys.
Note that when a command is used to compute a result, it may have further calls to
get(Key), which would in turn create their own computations. Thus a single call to
this method may populate the section manager with a large amount of objects, depending on the
the computation dependencies.
This method is the main entry point to interaction with the section manager. All computations should be done via the section manager commands, which would provide a good transactional environment with clear dependencies. For that reason, this method plays an important part in the default support for section management transactions, and dependency tracking.
If a result value for the given key is not available in the section manager, a command is used
to compute the value. This computation is wrapped in a start-cancel transaction. This means
that before the computation starts, a transaction for the key is started via
startTransaction(Key). Next, any exceptions caught during computation force the
cancellation of this transaction (see cancelTransaction(Key)). Thus for the majority
of commands, they only need to end the successful transaction (via
endTransaction(Key, Object, Collection)), and the starting/cancellation is handled
automatically.
On the other hand, this method is used to track dependencies for existing transactions. A call
to get(Key) indicates that a computation requires a certain object from the section
manager. Thus the computation (and result value) depends on this object. The keys of all calls
to get(Key) are collected for an existing transaction, and make up its implicit
dependencies. These calls may result in their own transactions started, if the value is not
computer, creating a nested tree of transactions, where "outer" transactions depend on "inner"
transactions and their values. The implicit dependencies are added to the key automatically,
when its transaction ends successfully.
T - Type of the key, and the value which is be resolved.key - The key to be looked up and resolved.CommandException - If the lookup/resolution was unsuccessful:
key.getType() value.SectionInfoException - Unchecked exception if computation is required, but constraints for starting the
transaction are violated (see startTransaction(Key) for details).SectionManager.get(Key)void startTransaction(Key<?> key) throws SectionInfoException
The section manager is updated with new results via transactions. So when computing a result to
cache in the section manager, a transaction needs to be started first, and then ended by
putting the computed result (see endTransaction(Key, Object)). Alternatively, if the
computation fails, the started transaction needs to be cancelled (see
cancelTransaction(Key)).
The transactional approach to section manager computations allows us to capture implicit
dependencies of the computed result. Between the start and end of transaction, all calls to
get(Key) in the section manager are tracked. E.g. when typechecking a ZSect "foo", the
command retrieves the parsed ZSect via #get(new Key<ZSect>("foo", ZSect.class)), and
typecheck results of parent ZSects, among others. These, in turn, will have implicit
dependencies on parent sections, etc. All these implicit dependencies through get(Key)
calls are assigned to the transaction upon its end.
By default, the implementors of section manager Commands do not need to start the transactions
manually. The get(Key) method starts the transaction automatically before the command
is executed - see get(Key) for details. However, in some cases, e.g. when the
computations are started on-the-fly (as opposed to via section manager commands, e.g.
calculating LatexMarkupFunction during parse), the transactions need to be started by this
method (or ensureTransaction(Key)). Other cases include postponing a transaction (see
postponeTransaction(Key, Key)), and then manually starting a transaction in the
correct order.
Note that if a transaction is started manually, handling of its cancellation upon
exceptions needs to be done manually as well. See cancelTransaction(Key) for details.
The start/end/cancel transaction functionality supersedes the previous put() style of updating
the section manager. The put(Key, Object) methods now are just a convenience for
starting and immediately ending the transaction.
In addition to transactions in the section manager, duplicate computations are no longer allowed. This means that a transaction cannot be started if the result has already been cached - it is required to remove the previous result before starting a new transaction. This is necessary to get correct dependencies. During removal of the key, all dependant objects are also cleaned from the section manager.
As part of the postponeTransaction(Key, Key), this method checks that the started
transaction is the one expected during the last postponeTransaction(Key, Key).
key - The key of the new transaction, indicating start of computation for the result.SectionInfoException - Unchecked exception if constraints for starting the transaction are violated:
key transaction cannot be already started - no overlapping transactions
on the same key.key result cannot be cached - no duplicate/overwritten results.key must be the one indicated as "expected" in the last call of
postponeTransaction(Key, Key).endTransaction(Key, Object),
cancelTransaction(Key),
ensureTransaction(Key),
get(Key)void ensureTransaction(Key<?> key) throws SectionInfoException
startTransaction(Key)
).
This method is used very similarly as the startTransaction(Key), however it does not
start a transaction if one has already been started. This can be used when it is not know if
the transaction has been started before, say, via a command.
Otherwise, the method is the same as startTransaction(Key), so refer to its comments
for details.
key - The key of the transaction to start (or check has already been started).SectionInfoException - Unchecked exception if constraints for ensuring the transaction are violated:
key transaction has already been started, it must be the currently
active transaction.key transaction has not been started, see exception cases in
startTransaction(Key).startTransaction(Key)<T> void endTransaction(Key<T> key, T value, Collection<? extends Key<?>> explicitDependencies) throws SectionInfoException
get(Key) calls since the start of transaction), as well as given
explicit dependencies are used.
The computed results can be stored in the section manager only as a part of the completed
transaction, using this method. This ensures strict contract on using the section manager, and
allows capturing implicit dependencies of the computation (see startTransaction(Key)
for more details). Note that transaction can only be ended upon successful computation (when
the result is available). Otherwise, it must be cancelled.
Ending of transactions is the main method to use in section manager Commands. When the result
is calculated, it should be put into the section manager using this method. In the default
case, the starting and cancelling (upon exception) of transaction is handled inside
get(Key), thus only ending the transaction is required in the command.
Note that the transactions must be nested, and cannot overlap. So we can only end the currently active transaction.
For the manually started transactions and exception-cancellation issues, please refer to
startTransaction(Key) and cancelTransaction(Key).
As outlined in startTransaction(Key), all get(Key) calls since the start of
transaction are collected as dependencies of this key. So in the case of parsing a ZSect, it
will collect dependencies on parent ZSects, its info tables, etc. These, in turn, will collect
their own dependencies on their parents, etc. This is achieved by a nesting of start-end of
transactions. The dependencies are stored in the section manager, and when one of the
dependencies is removed, this key is also (transitively) removed.
If some of the dependencies cannot be captured implicitly, the explicitDependencies
parameter allows indicating explicit dependencies. The following are several examples of such
cases:
T - The type of the computed value, as indicated by the key.key - The key referencing the value in the section manager. A transaction on this
key must be started, and will be completed with this method.value - The computed value, which can be referenced by the key in the section manager
afterwards. The value must exist and be of the type indicated by key.explicitDependencies - Explicit dependencies, if needed, for the indicated key.SectionInfoException - Unchecked exception if constraints for ending the transaction are violated:
null.key transaction must be the currently active one.key result cannot be cached - no duplicate/overwritten results.startTransaction(Key),
cancelTransaction(Key)<T> void endTransaction(Key<T> key, T value) throws SectionInfoException
endTransaction(Key, Object, Collection), with no
explicit dependencies. See endTransaction(Key, Object, Collection) for details.T - The type of the computed value, as indicated by the key.key - The key referencing the value in the section manager. A transaction on this
key must be started, and will be completed with this method.value - The computed value, which can be referenced by the key in the section manager
afterwards. The value must exist and be of the type indicated by key.SectionInfoException - Unchecked exception if constraints for ending the transaction are violated, see
endTransaction(Key, Object, Collection).endTransaction(Key, Object, Collection)Set<Key<?>> cancelTransaction(Key<?> key) throws SectionInfoException
Note that cancelling a transaction does not remove successful nested transactions, if they do not depend on the cancelled one. This means that after cancelling a top-level transaction, there can still be "leftovers" from its dependencies.
For example, if we parse a Z section "bar parents foo". Thus a transaction for "bar"
ZSect is started, which in turn has a nested transaction to calculate its parent, "foo" ZSect.
If "bar" fails with a parse exception, we still want to keep the successfully parsed parent
"foo" ZSect. Then when the "bar" error is corrected, there is no need to re-parse "foo" ZSect.
Note that "foo" does not depend on "bar" in any way, so we can leave it in the section manager
when cancelling "bar".
By default, the implementors of section manager Commands do not need to cancel the transactions
manually. The get(Key) method wraps the computation into a try-catch and cancels the
started transaction if an exception is encountered - see get(Key) for details.
However, when the commands are started manually via startTransaction(Key) (or
ensureTransaction(Key)), there is a need to handle exceptions manually as well. If
possible, the paths that can throw exceptions should catch them, cancel the transaction, and
re-throw the exception.
This method can also be used to end the transaction, when the result cannot be calculated. In
this case, it should be somewhere alongside endTransaction(Key, Object, Collection),
but cancelling if the value is null or invalid.
As a last resort, get(Key) implementations should cancel all nested un-cancelled
transactions if caught in exceptions. However, for good transactional implementation, the
errors of manual transactions should be managed by the commands themselves.
key - The key of currently active transaction, which needs to be cancelled. The key, and
everything that depends on it, will be removed from the section manager.SectionInfoException - Unchecked exception if constraints for cancelling the transaction are violated:
key cannot be null.key transaction must be the currently active one.startTransaction(Key),
get(Key)void postponeTransaction(Key<?> postponedKey, Key<?> nextKey) throws SectionInfoException
Some of the commands may calculate their results as part of a bigger calculation. The following
are several examples the illustrating need and use case for
postponeTransaction(Key, Key):
postponeTransaction(Key, Key) method is used to perform this reorder, indicating that
the LMF transaction will be postponed in favor of the ZSect, which may in turn perform the LMF
transaction again (i.e., postponed).get(Key)), the transactional
chain would be ZSect > Spec > ZSect. The initial ZSect transaction is postponed to get Spec >
ZSect.
This method is a strict version of the cancelTransaction(Key). It requires to indicate
the next expected transaction - it should be known when postponing. This will be verified when
the next transaction is started in startTransaction(Key). Furthermore, this method can
only be used for just-started transaction (which do not have any marked dependencies - no
get(Key) calls since starting it). This constraint ensures that we are not losing any
dependencies by postponing.
Because of these constraints, postponing (and thus reordering) the transactions should be used
as the first action in the command. If an inappropriate transaction has been started within
get(Key) right before launching the command, postponing it in favor of another
(larger) transaction allows to achieve the desired order.
postponedKey - The key of an active transaction to be be postponed. The indicated transaction must be
at the top of transaction stack (currently active). It will be cancelled by this
method. The transaction cannot have any dependencies marked for it (via
get(Key)).nextKey - The key for the next expected transaction. Indicates the transaction that the
postponed key is postponed in favor of. The next call to
startTransaction(Key) must match the indicated key.SectionInfoException - Unchecked exception if constraints for postponing the transaction are violated:
postponedKey and nextKey cannot be null.postponedKey must be the currently active transaction.postponedKey cannot have dependencies marked for it (via
get(Key)).nextKey cannot be already cached.nextKey cannot be an already active transaction.cancelTransaction(Key),
startTransaction(Key)Key<?> getCurrentTransaction()
null otherwise.<T> void put(Key<T> key, T value, Collection<? extends Key<?>> explicitDependencies) throws SectionInfoException
key. This method should be used when
there is no computation of the value, and thus no implicit dependencies are needed. So by using
this method, the value is simply put in the section manager, indicating no gap in the
transaction.
Note that the method starts a transaction, thus it must not be used if a transaction is already
active. In that case, endTransaction(Key, Object, Collection) must be used. Which is
the usual case for section manager commands.
The shorthand put(Key, Object, Collection) method is good for putting things that do
not depend on anything in the section manager, e.g. initial Source objects. However, the method
allows indicating explicit dependencies in explicitDependencies parameter.
T - The type of the value, as indicated by the key.key - The key referencing the value in the section manager. A transaction on this
key must will be started and immediately ended with this method.value - The value, which can be referenced by the key in the section manager
afterwards. The value must exist and be of the type indicated by key.explicitDependencies - Explicit dependencies, if needed, for the indicated key (e.g. the set of keys
that the value depends on - parents, etc.).SectionInfoException - Unchecked exception if constraints for starting and ending the transaction are
violated. See startTransaction(Key) and
endTransaction(Key, Object, Collection) for details.startTransaction(Key),
endTransaction(Key, Object, Collection)<T> void put(Key<T> key, T value) throws SectionInfoException
put(Key, Object, Collection), with no explicit
dependencies. Thus the call on this method indicates that the given key has no
dependencies altogether (neither implicit, nor explicit). See
put(Key, Object, Collection) for details.T - The type of the value, as indicated by the key.key - The key referencing the value in the section manager. A transaction on this
key must will be started and immediately ended with this method.value - The value, which can be referenced by the key in the section manager
afterwards. The value must exist and be of the type indicated by key.SectionInfoException - Unchecked exception if constraints for starting and ending the transaction are
violated. See put(Key, Object, Collection) for details.put(Key, Object, Collection)Set<Key<?>> keysOf(String name)
name - <T> Set<Key<? extends T>> keysOf(Class<T> clsName)
T - type of key classclsName - void reset()
throws SectionInfoException
Thus after resetting, there is no need to redo the work on CZT core toolkits.
The section manager cannot be reset if there are any ongoing transactions, because it will destroy the transactional integrity.
SectionInfoException - Unchecked exception if there are ongoing transactions.boolean isCached(Key<?> key)
key - The key to be looked up.<T> Key<? super T> retrieveKey(T value)
T - returned key typevalue - value to search for keyboolean removeKey(Key<?> key) throws SectionInfoException
For example, let A parents B, B parents C. Now if we remove B from the section
manager, it will also remove A, which depends on it, but not C. So now if we
want to recompute B, we no longer need to recompute C.
key - The key to be removed, including all of its dependants. It cannot be part of an
ongoing transaction.true if the removal was successful, false if there was no cached value
for the given key.SectionInfoException - Unchecked exception if the key or any of its dependent keys are current in a
transaction.Set<Key<?>> getDependants(Key<?> key)
key.
For example, let A parents B, B parents C. Then if key is for C,
the result is A and B, because they depend on C.
Note that the relationship can be transitive, i.e. not all keys are returned would need to be followed transitively to collect everything.
key - The key, which dependants are requested.key.Set<Key<?>> getDependencies(Key<?> key)
key depends on.
For example, let A parents B, B parents C. Then if key is for A,
the result is B and C, because A depends on them.
Note that the relationship can be transitive, i.e. not all keys are returned would need to be followed transitively to collect everything.
key - The key, which dependencies are requested.key depends.boolean setTracing(boolean on,
Level level)
SectionManager
uses a ConsoleHandler from the Java logging API.on - flag to set it on or offlevel - Level getTracingLevel()
setTracing(boolean, Level).boolean isTracing()
setTracing(boolean, Level).Copyright © 2003–2016 Community Z Tools Project. All rights reserved.