Created
February 28, 2012 13:56
-
-
Save jukka/1932695 to your computer and use it in GitHub Desktop.
jr3 tree model
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Map; | |
/** | |
* Trees are the key concept in a hierarchical content repository. | |
* This interface is a low-level tree node representation that just | |
* maps zero or more string names to corresponding child nodes. | |
* Depending on context, a Tree instance can be interpreted as | |
* representing just that tree node, the subtree starting at that node, | |
* or an entire tree in case it's a root node. | |
* <p> | |
* For familiarity and easy integration with existing libraries this | |
* interface extends the generic {@link Map} interface instead of | |
* providing a custom alternative. Note also that this interface is | |
* named Tree instead of something like Item or Node to avoid confusion | |
* with the related JCR interfaces. | |
* </p> | |
* | |
* <h2>Leaves and non-leaves</h2> | |
* <p> | |
* Normal tree nodes only contain structural information expressed as | |
* the set of child nodes and their names. The content of a tree, expressed | |
* in data types like strings, numbers and binaries, is stored in special | |
* leaf nodes with no children. Such leaf nodes implement the {@link Leaf} | |
* sub-interface and can be identified and accessed using the | |
* {@link #isLeaf()} and {@link #asLeaf()} methods. | |
* </p> | |
* <p> | |
* Note that even tough such leaf nodes are guaranteed to have no children | |
* (i.e. {@link #isLeaf()} implies {@link #isEmpty()}), the reverse is not | |
* necessarily true. It's possible for a non-leaf node to contain no children, | |
* though such cases occur normally only transiently when new subtrees are | |
* being constructed. | |
* </p> | |
* | |
* <h2>Mutability and thread-safety</h2> | |
* <p> | |
* Tree objects are immutable by default and thus safe for concurrent access. | |
* Using a mutator method like {@link #clear()} or {@link #put(String, Tree)} | |
* results in an {@link UnsupportedOperationException exception}. A new Tree | |
* instance is needed to express a modified content tree. As a result it's | |
* safe to repeat operations like iterating over all child nodes of a Tree | |
* instance and expect results to be the same. | |
* </p> | |
* <p> | |
* In specific situations like when constructing new trees it's possible for | |
* Tree instances to be mutable. Such cases need to be explicitly documented | |
* and managed in a way that prevents thread-safety issues, for example by | |
* keeping a reference to such a mutable Tree instance local to a single | |
* thread. | |
* </p> | |
* | |
* <h2>Persistence and error-handling</h2> | |
* <p> | |
* A Tree instance can be (and often is) backed by local files or network | |
* resources. All IO operations or related concerns like caching should be | |
* handled transparently below this interface. Potential IO problems and | |
* recovery attempts like retrying a timed-out network access need to be | |
* handled below this interface, and only hard errors should be thrown up | |
* as {@link RuntimeException unchecked exceptions} that higher level code | |
* is not expected to be able to recover from. | |
* </p> | |
* <p> | |
* Since this interface exposes no higher level constructs like access | |
* controls, locking, node types or even path parsing, there's no way | |
* for content access to fail because of such concerns. Such functionality | |
* and related checked exceptions or other control flow constructs should | |
* be implemented on a higher level above this interface. | |
* </p> | |
* | |
* <h2>Decoration and virtual content</h2> | |
* <p> | |
* Not all content exposed by Tree objects needs to be backed by actual | |
* persisted data. An implementation may want to provide provide derived | |
* data like for example the aggregate size of the entire subtree as an | |
* extra virtual leaf node. A virtualization, sharding or caching layer | |
* could provide a composite view over multiple underlying content trees. | |
* Or a basic access control layer could decide to hide certain content | |
* based on specific rules. All such features need to be implemented | |
* according to the API contract of this interface. A separate higher level | |
* interface needs to be used if an implementation can't for example | |
* guarantee immutability of exposed content as discussed above. | |
* </p> | |
*/ | |
interface Tree extends Map<String, Tree> { | |
/** | |
* Checks whether this is a {@link Leaf} instance. Can be used to | |
* control program flow without explicit <code>instanceof</code> checks | |
* for handling leaf content. See also the {@link #asLeaf()} method | |
* that can additionally take care of type casting. | |
* | |
* @return <code>true</code> if this is a {@link Leaf}, | |
* <code>false</code> if not | |
*/ | |
boolean isLeaf(); | |
/** | |
* Returns this instance as a {@link Leaf} if possible. Can be used | |
* to access leaf nodes without <code>instanceof</code> checks or | |
* explicit type casting. A typical access pattern is: | |
* <pre> | |
* Leaf leaf = tree.asLeaf(); | |
* if (leaf != null) { | |
* // handle leaf content | |
* } else { | |
* // handle non-leaf content | |
* } | |
* </pre> | |
* | |
* @return this instance as a {@link Leaf}, | |
* or <code>null</code> if this is a non-leaf node | |
*/ | |
Leaf asLeaf(); | |
} | |
/** | |
* Leaves are special {@link Tree} nodes contain typed data like strings, | |
* numbers, binaries, etc. This interface extends {@link Tree} and thus | |
* also {@link Map}, but all Leaf instances are guaranteed to contain zero | |
* child nodes. Leaves are always immutable. | |
*/ | |
interface Leaf extends Tree { | |
// TODO: Add data access methods | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment