public abstract class NamespaceBehaviour<K, V, N extends IdentifierNamespace<K, V>> implements Identifiable<Class<N>> {
public enum StorageNodeType {
- GLOBAL, SOURCE_LOCAL_SPECIAL, STATEMENT_LOCAL,
+ GLOBAL, SOURCE_LOCAL_SPECIAL, STATEMENT_LOCAL, ROOT_STATEMENT_LOCAL
}
public interface Registry {
}
public interface NamespaceStorageNode {
-
+ /**
+ * @return local namespace behaviour type {@link NamespaceBehaviour}
+ */
StorageNodeType getStorageNodeType();
@Nullable
@Nullable
<K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAllFromLocalStorage(Class<N> type);
+ /**
+ * Populate specified namespace with a key/value pair, overwriting previous contents. Similar to
+ * {@link Map#put(Object, Object)}.
+ *
+ * @param type Namespace identifier
+ * @param key Key
+ * @param value Value
+ * @return Previously-stored value, or null if the key was not present
+ */
@Nullable
- <K, V, N extends IdentifierNamespace<K, V>> void addToLocalStorage(Class<N> type, K key, V value);
-
+ <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorage(Class<N> type, K key, V value);
+
+ /**
+ * Populate specified namespace with a key/value pair unless the key is already associated with a value. Similar
+ * to {@link Map#putIfAbsent(Object, Object)}.
+ *
+ * @param type Namespace identifier
+ * @param key Key
+ * @param value Value
+ * @return Preexisting value or null if there was no previous mapping
+ */
+ @Nullable
+ <K, V, N extends IdentifierNamespace<K, V>> V putToLocalStorageIfAbsent(Class<N> type, K key, V value);
}
private final Class<N> identifier;
- protected NamespaceBehaviour(Class<N> identifier) {
+ protected NamespaceBehaviour(final Class<N> identifier) {
this.identifier = Preconditions.checkNotNull(identifier);
}
* @return global namespace behaviour for supplied namespace type.
*/
public static @Nonnull <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> global(
- Class<N> identifier) {
+ final Class<N> identifier) {
return new StorageSpecific<>(identifier, StorageNodeType.GLOBAL);
}
* @return source-local namespace behaviour for supplied namespace type.
*/
public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> sourceLocal(
- Class<N> identifier) {
+ final Class<N> identifier) {
return new StorageSpecific<>(identifier, StorageNodeType.SOURCE_LOCAL_SPECIAL);
}
public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> statementLocal(
- Class<N> identifier) {
+ final Class<N> identifier) {
return new StorageSpecific<>(identifier, StorageNodeType.STATEMENT_LOCAL);
}
*
* @return tree-scoped namespace behaviour for supplied namespace type.
*/
- public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> treeScoped(Class<N> identifier) {
+ public static <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> treeScoped(final Class<N> identifier) {
return new TreeScoped<>(identifier);
}
return identifier;
}
- protected final V getFromLocalStorage(NamespaceStorageNode storage, K key) {
+ protected final V getFromLocalStorage(final NamespaceStorageNode storage, final K key) {
return storage.getFromLocalStorage(getIdentifier(), key);
}
- protected final Map<K, V> getAllFromLocalStorage(NamespaceStorageNode storage) {
+ protected final Map<K, V> getAllFromLocalStorage(final NamespaceStorageNode storage) {
return storage.getAllFromLocalStorage(getIdentifier());
}
- protected final void addToStorage(NamespaceStorageNode storage, K key, V value) {
- storage.addToLocalStorage(getIdentifier(), key, value);
+ protected final void addToStorage(final NamespaceStorageNode storage, final K key, final V value) {
+ storage.putToLocalStorage(getIdentifier(), key, value);
}
static class StorageSpecific<K, V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
StorageNodeType storageType;
- public StorageSpecific(Class<N> identifier, StorageNodeType type) {
+ public StorageSpecific(final Class<N> identifier, final StorageNodeType type) {
super(identifier);
storageType = Preconditions.checkNotNull(type);
}
@Override
public V getFrom(final NamespaceStorageNode storage, final K key) {
- NamespaceStorageNode current = storage;
- while (current.getStorageNodeType() != storageType) {
- current = current.getParentNamespaceStorage();
- }
+ NamespaceStorageNode current = findClosestTowardsRoot(storage, storageType);
return getFromLocalStorage(current, key);
}
}
@Override
- public void addTo(NamespaceBehaviour.NamespaceStorageNode storage, K key, V value) {
- NamespaceStorageNode current = storage;
- while (current.getStorageNodeType() != storageType) {
- current = current.getParentNamespaceStorage();
- }
+ public void addTo(final NamespaceBehaviour.NamespaceStorageNode storage, final K key, final V value) {
+ NamespaceStorageNode current = findClosestTowardsRoot(storage, storageType);
addToStorage(current, key, value);
}
static class TreeScoped<K, V, N extends IdentifierNamespace<K, V>> extends NamespaceBehaviour<K, V, N> {
- public TreeScoped(Class<N> identifier) {
+ public TreeScoped(final Class<N> identifier) {
super(identifier);
}
}
@Override
- public void addTo(NamespaceStorageNode storage, K key, V value) {
+ public void addTo(final NamespaceStorageNode storage, final K key, final V value) {
addToStorage(storage, key, value);
}
}
+
+ protected static NamespaceStorageNode findClosestTowardsRoot(final NamespaceStorageNode storage, final StorageNodeType type) {
+ NamespaceStorageNode current = storage;
+ while (current != null && current.getStorageNodeType() != type) {
+ current = current.getParentNamespaceStorage();
+ }
+ return current;
+ }
}