summaryrefslogtreecommitdiff
path: root/src/main/java/bjc/data/Contexts.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/bjc/data/Contexts.java')
-rw-r--r--src/main/java/bjc/data/Contexts.java103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/main/java/bjc/data/Contexts.java b/src/main/java/bjc/data/Contexts.java
new file mode 100644
index 0000000..b028ad1
--- /dev/null
+++ b/src/main/java/bjc/data/Contexts.java
@@ -0,0 +1,103 @@
+package bjc.data;
+
+import java.util.*;
+
+/**
+ * Utility methods for dealing with contexts.
+ *
+ * @author Ben Culkin
+ *
+ */
+public class Contexts {
+ /**
+ * The null context, which always throws an exception.
+ */
+ public static final Context NULL = new NullContextImpl();
+
+ private Contexts() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Create a new context with no parent.
+ *
+ * @return A context with no parent.
+ */
+ public static Context create() {
+ return new ContextImpl(NULL);
+ }
+
+ /**
+ * Create a context with the specified parent.
+ *
+ * @param parent The parent of this context.
+ *
+ * @return A context with the given context as its parent.
+ */
+ public static Context create(Context parent) {
+ return new ContextImpl(parent);
+ }
+
+ private static class NullContextImpl implements Context {
+ @Override
+ public Context getParent() {
+ return this;
+ }
+
+ @Override
+ public void register(String name, Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object get(String name) {
+ throw new NoSuchElementException();
+ }
+
+ @Override
+ public <T> T get(Class<T> contract) {
+ throw new NoSuchElementException();
+ }
+ }
+
+ private static class ContextImpl implements Context {
+
+ private final Context parent;
+
+ private final Map<String, Object> objects;
+
+ public ContextImpl(Context parent) {
+ this.parent = parent;
+ this.objects = new HashMap<>();
+ }
+
+ @Override
+ public void register(String name, Object o) {
+ objects.put(name, o);
+ }
+
+ @Override
+ public Object get(String name) {
+ if (objects.containsKey(name)) {
+ return objects.get(name);
+ }
+ return parent.get(name);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T get(Class<T> contract) {
+ for (Object o : objects.values()) {
+ if (contract.isInstance(o)) {
+ return (T) o;
+ }
+ }
+ return parent.get(contract);
+ }
+
+ @Override
+ public Context getParent() {
+ return parent;
+ }
+ }
+}