From a6be24c59d49de695525b87e7081b2e13beb8769 Mon Sep 17 00:00:00 2001
From: Speiger <speiger@gmx.net>
Date: Sun, 2 Jul 2023 01:22:04 +0200
Subject: [PATCH] Start of a Advanced Dependency System.

The idea behind this system is that you can select systems a lot easier.
So if a custom system isn't required it can be disabled and all the
subsystems that require it either get disabled too.
it also allows you to set systems as: Only if they are required. Meaning
if only a specific system is required its dependencies can still load.
---
 .../builder/dependency/DependencyBase.java    |  51 ++++++
 .../dependency/DependencyFunction.java        | 109 ++++++++++++
 .../builder/dependency/DependencyModule.java  | 158 ++++++++++++++++++
 .../builder/dependency/DependencyType.java    |  31 ++++
 .../builder/dependency/DependencyValue.java   |  32 ++++
 .../src/builder/dependency/IDependency.java   |  40 +++++
 .../src/builder/modules/AsyncModule.java      |   9 +-
 .../src/builder/modules/BaseModule.java       |   6 +
 .../src/builder/modules/CollectionModule.java |  35 ++--
 .../src/builder/modules/FunctionModule.java   |   3 +
 .../src/builder/modules/JavaModule.java       |   3 +
 .../src/builder/modules/ListModule.java       |  38 +++--
 .../src/builder/modules/MapModule.java        | 105 ++++++------
 .../src/builder/modules/PairModule.java       |  19 ++-
 .../src/builder/modules/PrioQueueModule.java  |  39 +++--
 .../src/builder/modules/SetModule.java        |  81 +++++----
 16 files changed, 616 insertions(+), 143 deletions(-)
 create mode 100644 src/builder/java/speiger/src/builder/dependency/DependencyBase.java
 create mode 100644 src/builder/java/speiger/src/builder/dependency/DependencyFunction.java
 create mode 100644 src/builder/java/speiger/src/builder/dependency/DependencyModule.java
 create mode 100644 src/builder/java/speiger/src/builder/dependency/DependencyType.java
 create mode 100644 src/builder/java/speiger/src/builder/dependency/DependencyValue.java
 create mode 100644 src/builder/java/speiger/src/builder/dependency/IDependency.java

diff --git a/src/builder/java/speiger/src/builder/dependency/DependencyBase.java b/src/builder/java/speiger/src/builder/dependency/DependencyBase.java
new file mode 100644
index 00000000..c925cce7
--- /dev/null
+++ b/src/builder/java/speiger/src/builder/dependency/DependencyBase.java
@@ -0,0 +1,51 @@
+package speiger.src.builder.dependency;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import speiger.src.builder.ClassType;
+
+@SuppressWarnings("javadoc")
+public abstract class DependencyBase implements IDependency {
+	protected List<IDependency> children = new ArrayList<>();
+	protected List<IDependency> parents = new ArrayList<>();
+
+	public <T extends DependencyBase> T addChild(T child) {
+		children.add(child);
+		child.addParent(this);
+		return child;
+	}
+	
+	public <T extends DependencyBase> T addParent(DependencyBase parent) {
+		parents.add(parent);
+		return (T) this;
+	}
+	
+	public List<IDependency> getParents() {
+		return parents;
+	}
+	
+	public List<IDependency> getChildren() {
+		return children;
+	}
+	
+	public abstract boolean resolveDependencies();
+	
+	protected LoadingState getChildState(ClassType keyType, ClassType valueType) {
+		LoadingState state = LoadingState.UNDEFINED;
+		for(IDependency child : children) {
+			if(state == LoadingState.LOADED) return LoadingState.LOADED;
+			state = state.mergeDown(child.getState(keyType, valueType));
+		}
+		return state;
+	}
+	
+	protected LoadingState getParentState(ClassType keyType, ClassType valueType) {
+		LoadingState state = LoadingState.UNDEFINED;
+		for(IDependency parent : parents) {
+			if(state == LoadingState.UNLOADED) return LoadingState.UNLOADED;
+			state = state.mergeUp(parent.getState(keyType, valueType));
+		}
+		return state;
+	}
+}
diff --git a/src/builder/java/speiger/src/builder/dependency/DependencyFunction.java b/src/builder/java/speiger/src/builder/dependency/DependencyFunction.java
new file mode 100644
index 00000000..d3291caf
--- /dev/null
+++ b/src/builder/java/speiger/src/builder/dependency/DependencyFunction.java
@@ -0,0 +1,109 @@
+package speiger.src.builder.dependency;
+
+import java.util.Arrays;
+
+import com.google.gson.JsonObject;
+
+import speiger.src.builder.ClassType;
+
+@SuppressWarnings("javadoc")
+public abstract class DependencyFunction extends DependencyBase {
+	protected DependencyModule owner;
+	
+	public DependencyFunction(DependencyModule owner) {
+		this.owner = owner;
+	}
+	
+	@Override
+	public boolean isEnabled() {
+		return getState(owner.owner.keyType(), owner.owner.valueType()) == LoadingState.LOADED;
+	}
+	
+	public abstract DependencyFunction createSubFunction(String function);
+	
+	public static class SingleFunction extends DependencyFunction {
+		LoadingState[] state = new LoadingState[ClassType.values().length];
+		String functionName;
+		
+		public SingleFunction(DependencyModule owner, String functionName) {
+			super(owner);
+			this.functionName = functionName;
+			Arrays.fill(state, LoadingState.UNDEFINED);
+		}
+		
+		@Override
+		public DependencyFunction createSubFunction(String function) {
+			return addChild(new SingleFunction(owner, function));
+		}
+		
+		@Override
+		public void load(JsonObject obj, ClassType keyType, ClassType valueType) {
+			state[keyType.ordinal()] = owner.isFunctionLoaded(obj, keyType, valueType, functionName);
+		}
+
+		@Override
+		public LoadingState getState(ClassType keyType, ClassType valueType) {
+			return state[keyType.ordinal()];
+		}
+
+		@Override
+		public boolean resolveDependencies() {
+			boolean returnType = false;
+			for(ClassType type : ClassType.values()) {
+				LoadingState state = this.state[type.ordinal()];
+				if(state == LoadingState.UNLOADED) continue;
+				state = state.merge(getChildState(type, type)).merge(getParentState(type, type));
+				if(state != this.state[type.ordinal()]) {
+					this.state[type.ordinal()] = state;
+					returnType = true;
+				}
+			}
+			return returnType;
+		}
+	}
+	
+	public static class BiTypeFunction extends DependencyFunction {
+		LoadingState[][] state = new LoadingState[ClassType.values().length][ClassType.values().length];
+		String functionName;
+		
+		BiTypeFunction(DependencyModule owner, String functionName) {
+			super(owner);
+			this.functionName = functionName;
+			for(int i = 0;i<state.length;i++) {
+				Arrays.fill(state[i], LoadingState.UNDEFINED);
+			}
+		}
+		
+		@Override
+		public DependencyFunction createSubFunction(String function) {
+			return new BiTypeFunction(owner, function);
+		}
+		
+		@Override
+		public void load(JsonObject obj, ClassType keyType, ClassType valueType) {
+			state[keyType.ordinal()][valueType.ordinal()] = owner.isFunctionLoaded(obj, keyType, valueType, functionName);
+		}
+		
+		@Override
+		public LoadingState getState(ClassType keyType, ClassType valueType) {
+			return state[keyType.ordinal()][valueType.ordinal()];
+		}
+		
+		@Override
+		public boolean resolveDependencies() {
+			boolean returnType = false;
+			for(ClassType keyType : ClassType.values()) {
+				for(ClassType valueType : ClassType.values()) {
+					LoadingState state = this.state[keyType.ordinal()][valueType.ordinal()];
+					if(state == LoadingState.UNLOADED) continue;
+					state = state.merge(getChildState(keyType, valueType)).merge(getParentState(keyType, valueType));
+					if(state != this.state[keyType.ordinal()][valueType.ordinal()]) {
+						this.state[keyType.ordinal()][valueType.ordinal()] = state;
+						returnType = true;
+					}
+				}
+			}
+			return returnType;
+		}
+	}
+}
diff --git a/src/builder/java/speiger/src/builder/dependency/DependencyModule.java b/src/builder/java/speiger/src/builder/dependency/DependencyModule.java
new file mode 100644
index 00000000..8170583f
--- /dev/null
+++ b/src/builder/java/speiger/src/builder/dependency/DependencyModule.java
@@ -0,0 +1,158 @@
+package speiger.src.builder.dependency;
+
+import java.util.Arrays;
+
+import com.google.gson.JsonObject;
+
+import speiger.src.builder.ClassType;
+import speiger.src.builder.dependency.DependencyFunction.BiTypeFunction;
+import speiger.src.builder.dependency.DependencyFunction.SingleFunction;
+import speiger.src.builder.modules.BaseModule;
+
+@SuppressWarnings("javadoc")
+public abstract class DependencyModule extends DependencyBase {
+	protected BaseModule owner;
+	
+	public DependencyModule(BaseModule owner) {
+		this.owner = owner;
+	}
+	
+	public LoadingState isFunctionLoaded(JsonObject obj, ClassType keyType, ClassType valueType, String function) { return isModuleEnabled(obj, keyType, valueType, function); }
+	
+	public abstract DependencyFunction createFunction(String functionName);
+	
+	@Override
+	public boolean isEnabled() {
+		return getState(owner.keyType(), owner.valueType()) == LoadingState.LOADED;
+	}
+	
+	public static class SingleTypeModule extends DependencyModule {
+		LoadingState[] state = new LoadingState[ClassType.values().length];
+		
+		public SingleTypeModule(BaseModule owner) {
+			super(owner);
+			Arrays.fill(state, LoadingState.UNDEFINED);
+		}
+		
+		@Override
+		public DependencyFunction createFunction(String functionName) {
+			return addChild(new SingleFunction(this, functionName));
+		}
+		
+		@Override
+		public void load(JsonObject obj, ClassType keyType, ClassType valueType) {
+			state[keyType.ordinal()] = isModuleEnabled(obj, keyType, valueType);
+		}
+		
+		@Override
+		public LoadingState getState(ClassType keyType, ClassType valueType) {
+			return state[keyType.ordinal()];
+		}
+		
+		@Override
+		public boolean resolveDependencies() {
+			boolean returnType = false;
+			for(ClassType type : ClassType.values()) {
+				LoadingState state = this.state[type.ordinal()];
+				if(state == LoadingState.UNLOADED) continue;
+				state = state.merge(getChildState(type, type)).merge(getParentState(type, type));
+				if(state != this.state[type.ordinal()]) {
+					this.state[type.ordinal()] = state;
+					returnType = true;
+				}
+			}
+			return returnType;
+		}
+	}
+	
+	public static class BiTypeModule extends DependencyModule {
+		LoadingState[][] state = new LoadingState[ClassType.values().length][ClassType.values().length];
+
+		public BiTypeModule(BaseModule owner) {
+			super(owner);
+			for(int i = 0;i<state.length;i++) {
+				Arrays.fill(state[i], LoadingState.UNDEFINED);
+			}
+		}
+		
+		@Override
+		public DependencyFunction createFunction(String functionName) {
+			return addChild(new BiTypeFunction(this, functionName));
+		}
+		
+		@Override
+		public void load(JsonObject obj, ClassType keyType, ClassType valueType) {
+			state[keyType.ordinal()][valueType.ordinal()] = isModuleEnabled(obj, keyType, valueType);
+		}
+		
+		@Override
+		public LoadingState getState(ClassType keyType, ClassType valueType) {
+			return state[keyType.ordinal()][valueType.ordinal()];
+		}
+		
+		@Override
+		public boolean resolveDependencies() {
+			boolean returnType = false;
+			for(ClassType keyType : ClassType.values()) {
+				for(ClassType valueType : ClassType.values()) {
+					LoadingState state = this.state[keyType.ordinal()][valueType.ordinal()];
+					if(state == LoadingState.UNLOADED) continue;
+					state = state.merge(getChildState(keyType, valueType)).merge(getParentState(keyType, valueType));
+					if(state != this.state[keyType.ordinal()][valueType.ordinal()]) {
+						this.state[keyType.ordinal()][valueType.ordinal()] = state;
+						returnType = true;
+					}
+				}
+			}
+			return returnType;
+		}
+	}
+	
+	protected LoadingState isModuleEnabled(JsonObject data, ClassType keyType, ClassType valueType) {
+		LoadingState state = isEnabled(data, owner.getModuleName());
+		if(state != LoadingState.UNDEFINED) return state;
+		JsonObject result = getObject(data, keyType.getClassPath(), false);
+		state = isEnabled(result, "Enabled");
+		if(state != LoadingState.UNDEFINED) return state;
+		if(owner.isBiModule()) {
+			result = getObject(result, valueType.getClassPath(), false);
+			state = isEnabled(result, "Enabled");
+			if (state != LoadingState.UNDEFINED) return state;
+		}
+		return isEnabled(getObject(result, owner.getModuleName(), false), "Enabled");
+	}
+	
+	protected LoadingState isModuleEnabled(JsonObject data, ClassType keyType, ClassType valueType, String entry) {
+		LoadingState state = isEnabled(data, owner.getModuleName());
+		if(state != LoadingState.UNDEFINED) return state;
+		JsonObject result = getObject(data, keyType.getClassPath(), false);
+		state = isEnabled(result, "Enabled");
+		if(state != LoadingState.UNDEFINED) return state;
+		if(owner.isBiModule()) {
+			result = getObject(result, valueType.getClassPath(), false);
+			state = isEnabled(result, "Enabled");
+			if(state != LoadingState.UNDEFINED) return state;
+		}
+		result = getObject(result, owner.getModuleName(), false);
+		state = isEnabled(result, "Enabled");
+		if(state != LoadingState.UNDEFINED) return state;
+		return isEnabled(result, entry);
+	}
+
+	private JsonObject getObject(JsonObject data, String name, boolean create) {
+		JsonObject obj = data.getAsJsonObject(name);
+		if (obj == null) {
+			obj = new JsonObject();
+			data.add(name, obj);
+			if (create)
+				obj.addProperty("Enabled", true);
+		}
+		return obj;
+	}
+
+	private LoadingState isEnabled(JsonObject obj, String key) {
+		if (obj.has(key))
+			return LoadingState.of(obj.getAsJsonPrimitive(key).getAsBoolean());
+		return LoadingState.UNDEFINED;
+	}
+}
diff --git a/src/builder/java/speiger/src/builder/dependency/DependencyType.java b/src/builder/java/speiger/src/builder/dependency/DependencyType.java
new file mode 100644
index 00000000..270c5c9a
--- /dev/null
+++ b/src/builder/java/speiger/src/builder/dependency/DependencyType.java
@@ -0,0 +1,31 @@
+package speiger.src.builder.dependency;
+
+import com.google.gson.JsonObject;
+
+import speiger.src.builder.ClassType;
+
+@SuppressWarnings("javadoc")
+public class DependencyType extends DependencyBase {
+	DependencyBase owner;
+	ClassType myType;
+	
+	public DependencyType(DependencyBase owner, ClassType myType) {
+		this.owner = owner;
+		this.myType = myType;
+	}
+
+	@Override
+	public void load(JsonObject obj, ClassType keyType, ClassType valueType) {}
+	
+	@Override
+	public LoadingState getState(ClassType keyType, ClassType valueType) {
+		return owner.getState(myType, myType);
+	}
+	
+	@Override
+	public boolean resolveDependencies() { return false; }
+	@Override
+	public boolean isEnabled() {
+		return owner.getState(myType, myType) == LoadingState.LOADED;
+	}
+}
diff --git a/src/builder/java/speiger/src/builder/dependency/DependencyValue.java b/src/builder/java/speiger/src/builder/dependency/DependencyValue.java
new file mode 100644
index 00000000..9a5cbc25
--- /dev/null
+++ b/src/builder/java/speiger/src/builder/dependency/DependencyValue.java
@@ -0,0 +1,32 @@
+package speiger.src.builder.dependency;
+
+import com.google.gson.JsonObject;
+
+import speiger.src.builder.ClassType;
+
+@SuppressWarnings("javadoc")
+public class DependencyValue extends DependencyBase {
+	DependencyBase owner;
+	
+	public DependencyValue(DependencyBase owner) {
+		this.owner = owner;
+	}
+	
+	@Override
+	public void load(JsonObject obj, ClassType keyType, ClassType valueType) {}
+
+	@Override
+	public LoadingState getState(ClassType keyType, ClassType valueType) {
+		return owner.getState(valueType, keyType);
+	}
+	
+	@Override
+	public boolean resolveDependencies() {
+		return false;
+	}
+	
+	@Override
+	public boolean isEnabled() {
+		return owner.isEnabled();
+	}
+}
diff --git a/src/builder/java/speiger/src/builder/dependency/IDependency.java b/src/builder/java/speiger/src/builder/dependency/IDependency.java
new file mode 100644
index 00000000..5d1d1e87
--- /dev/null
+++ b/src/builder/java/speiger/src/builder/dependency/IDependency.java
@@ -0,0 +1,40 @@
+package speiger.src.builder.dependency;
+
+import com.google.gson.JsonObject;
+
+import speiger.src.builder.ClassType;
+
+@SuppressWarnings("javadoc")
+public interface IDependency {
+	public void load(JsonObject obj, ClassType keyType, ClassType valueType);
+	public LoadingState getState(ClassType keyType, ClassType valueType);
+	public boolean isEnabled();
+	
+	public static enum LoadingState {
+		UNDEFINED,
+		LOADED,
+		UNLOADED;
+		
+		public static LoadingState of(boolean value) {
+			return value ? LOADED : UNLOADED;
+		}
+		
+		public LoadingState merge(LoadingState merge) {
+			return ordinal() > merge.ordinal() ? this : merge;
+		}
+		
+		public LoadingState mergeDown(LoadingState merge) {
+			if(merge == UNLOADED || ordinal() > merge.ordinal()) {
+				return this;
+			}
+			return merge;
+		}
+		
+		public LoadingState mergeUp(LoadingState merge) {
+			if(merge == LOADED || ordinal() > merge.ordinal()) {
+				return this;
+			}
+			return merge;
+		}
+	}
+}
diff --git a/src/builder/java/speiger/src/builder/modules/AsyncModule.java b/src/builder/java/speiger/src/builder/modules/AsyncModule.java
index 75a0eb57..9df9331a 100644
--- a/src/builder/java/speiger/src/builder/modules/AsyncModule.java
+++ b/src/builder/java/speiger/src/builder/modules/AsyncModule.java
@@ -1,9 +1,14 @@
 package speiger.src.builder.modules;
 
+import speiger.src.builder.dependency.DependencyModule;
+import speiger.src.builder.dependency.DependencyModule.SingleTypeModule;
+
 @SuppressWarnings("javadoc")
 public class AsyncModule extends BaseModule
 {
 	public static final BaseModule INSTANCE = new AsyncModule();
+	public static final DependencyModule MODULE = CollectionModule.MODULE.addChild(new SingleTypeModule(INSTANCE));
+	
 	
 	@Override
 	public String getModuleName() { return "Async"; }
@@ -19,13 +24,13 @@ public class AsyncModule extends BaseModule
 	public boolean areDependenciesLoaded() { return isDependencyLoaded(CollectionModule.INSTANCE); }
 	@Override
 	protected void loadBlockades() {
-		if(!isModuleEnabled()) {
+		if(MODULE.isEnabled()) {
 			addBlockedFiles("AsyncBuilder", "Task");
 		}
 	}
 	@Override
 	protected void loadFlags() {
-		if(isModuleEnabled()) {
+		if(MODULE.isEnabled()) {
 			addKeyFlag("ASYNC_MODULE");
 		}
 	}
diff --git a/src/builder/java/speiger/src/builder/modules/BaseModule.java b/src/builder/java/speiger/src/builder/modules/BaseModule.java
index 866b7297..27ca50a2 100644
--- a/src/builder/java/speiger/src/builder/modules/BaseModule.java
+++ b/src/builder/java/speiger/src/builder/modules/BaseModule.java
@@ -2,6 +2,7 @@ package speiger.src.builder.modules;
 
 import java.util.Collections;
 import java.util.Set;
+import java.util.function.Consumer;
 import java.util.function.Predicate;
 
 import speiger.src.builder.ClassType;
@@ -205,4 +206,9 @@ public abstract class BaseModule
 		entry.addMapper(mapper);
 		return mapper;
 	}
+	
+	public static <T> T make(T input, Consumer<T> processor) {
+		processor.accept(input);
+		return input;
+	}
 }
diff --git a/src/builder/java/speiger/src/builder/modules/CollectionModule.java b/src/builder/java/speiger/src/builder/modules/CollectionModule.java
index 4987a423..70cc888d 100644
--- a/src/builder/java/speiger/src/builder/modules/CollectionModule.java
+++ b/src/builder/java/speiger/src/builder/modules/CollectionModule.java
@@ -5,48 +5,57 @@ import java.util.Set;
 import java.util.TreeSet;
 
 import speiger.src.builder.ClassType;
+import speiger.src.builder.dependency.DependencyFunction;
+import speiger.src.builder.dependency.DependencyModule;
+import speiger.src.builder.dependency.DependencyModule.SingleTypeModule;
 
 @SuppressWarnings("javadoc")
 public class CollectionModule extends BaseModule
 {
 	public static final BaseModule INSTANCE = new CollectionModule();
+	public static final DependencyModule MODULE = JavaModule.MODULE.addChild(new SingleTypeModule(INSTANCE));
+	public static final DependencyFunction STREAMS = MODULE.createFunction("Streams");
+	public static final DependencyFunction SPLIT_ITERATORS = MODULE.createFunction("Splititerators");
+	public static final DependencyFunction IARRAY = MODULE.createFunction("IArray");
+	public static final DependencyFunction STRATEGY = MODULE.createFunction("Strategy");
 	
 	@Override
 	public String getModuleName() { return "Collection"; }
 	@Override
 	protected void loadVariables() {}
 	@Override
-	public boolean areDependenciesLoaded(){ return isDependencyLoaded(JavaModule.INSTANCE); }
+	public boolean areDependenciesLoaded() { return isDependencyLoaded(JavaModule.INSTANCE); }
 	
 	@Override
-	public Set<String> getModuleKeys(ClassType keyType, ClassType valueType)
-	{
+	public Set<String> getModuleKeys(ClassType keyType, ClassType valueType) {
 		return new TreeSet<>(Arrays.asList("Streams", "Splititerators", "IArray", "Strategy"));
 	}
 	
 	@Override
 	protected void loadFlags() {
-		if(isModuleEnabled()) addKeyFlag("COLLECTION_MODULE");
-		if(isModuleEnabled("Streams")) addKeyFlag("STREAM_FEATURE");
-		if(isModuleEnabled("Splititerators")) addKeyFlag("SPLIT_ITERATOR_FEATURE");
-		if(isModuleEnabled("IArray")) addKeyFlag("IARRAY_FEATURE");
+		if(MODULE.isEnabled()) addKeyFlag("COLLECTION_MODULE");
+		if(STREAMS.isEnabled()) addKeyFlag("STREAM_FEATURE");
+		if(SPLIT_ITERATORS.isEnabled()) addKeyFlag("SPLIT_ITERATOR_FEATURE");
+		if(IARRAY.isEnabled()) addKeyFlag("IARRAY_FEATURE");
 	}
 	
 	@Override
 	protected void loadBlockades() {
-		if(!isModuleEnabled()) {
+		if(!MODULE.isEnabled()) {
 			addBlockedFiles("Iterable", "Iterables", "Iterator", "Iterators", "BidirectionalIterator", "ListIterator");
 			addBlockedFiles("Arrays", "Collection", "AbstractCollection", "Collections", "Stack");
 		}
-		if(!isModuleEnabled("Splititerators")) addBlockedFiles("Splititerator", "Splititerators");
-		if(!isModuleEnabled("IArray")) addBlockedFiles("IArray");
-		if(!isModuleEnabled("Strategy")) addBlockedFiles("Strategy");
+		if(!SPLIT_ITERATORS.isEnabled()) addBlockedFiles("Splititerator", "Splititerators");
+		if(!IARRAY.isEnabled()) addBlockedFiles("IArray");
+		if(!STRATEGY.isEnabled()) addBlockedFiles("Strategy");
 		
-		if(keyType.isObject()) {
+		if(keyType.isObject())
+		{
 			addBlockedFiles("Stack");
 			addBlockedFiles("CollectionStreamTester");
 		}
-		if(keyType == ClassType.BOOLEAN) {
+		if(keyType == ClassType.BOOLEAN)
+		{
 			addBlockedFiles("CollectionRemoveIfTester", "CollectionStreamTester");
 			addBlockedFilter(T -> T.endsWith("Tester") && T.startsWith("Iterable"));
 		}
diff --git a/src/builder/java/speiger/src/builder/modules/FunctionModule.java b/src/builder/java/speiger/src/builder/modules/FunctionModule.java
index 999f457c..54c53ab3 100644
--- a/src/builder/java/speiger/src/builder/modules/FunctionModule.java
+++ b/src/builder/java/speiger/src/builder/modules/FunctionModule.java
@@ -2,11 +2,14 @@ package speiger.src.builder.modules;
 
 import speiger.src.builder.ClassType;
 import speiger.src.builder.RequiredType;
+import speiger.src.builder.dependency.DependencyModule;
+import speiger.src.builder.dependency.DependencyModule.BiTypeModule;
 
 @SuppressWarnings("javadoc")
 public class FunctionModule extends BaseModule
 {
 	public static final BaseModule INSTANCE = new FunctionModule();
+	public static final DependencyModule MODULE = new BiTypeModule(INSTANCE);
 	
 	@Override
 	public String getModuleName() { return "Function"; }
diff --git a/src/builder/java/speiger/src/builder/modules/JavaModule.java b/src/builder/java/speiger/src/builder/modules/JavaModule.java
index e1725070..cc152906 100644
--- a/src/builder/java/speiger/src/builder/modules/JavaModule.java
+++ b/src/builder/java/speiger/src/builder/modules/JavaModule.java
@@ -1,11 +1,14 @@
 package speiger.src.builder.modules;
 
 import speiger.src.builder.ClassType;
+import speiger.src.builder.dependency.DependencyBase;
+import speiger.src.builder.dependency.DependencyModule.SingleTypeModule;
 
 @SuppressWarnings("javadoc")
 public class JavaModule extends BaseModule
 {
 	public static final BaseModule INSTANCE = new JavaModule();
+	public static final DependencyBase MODULE = new SingleTypeModule(INSTANCE);
 	
 	@Override
 	public String getModuleName() { return "Base"; }
diff --git a/src/builder/java/speiger/src/builder/modules/ListModule.java b/src/builder/java/speiger/src/builder/modules/ListModule.java
index e8881f07..ab62e0a4 100644
--- a/src/builder/java/speiger/src/builder/modules/ListModule.java
+++ b/src/builder/java/speiger/src/builder/modules/ListModule.java
@@ -5,37 +5,45 @@ import java.util.Set;
 import java.util.TreeSet;
 
 import speiger.src.builder.ClassType;
+import speiger.src.builder.dependency.DependencyFunction;
+import speiger.src.builder.dependency.DependencyModule;
+import speiger.src.builder.dependency.DependencyModule.SingleTypeModule;
 
 @SuppressWarnings("javadoc")
 public class ListModule extends BaseModule
 {
 	public static final BaseModule INSTANCE = new ListModule();
-	
+	public static final DependencyModule MODULE = CollectionModule.MODULE.addChild(new SingleTypeModule(INSTANCE));
+	public static final DependencyFunction IMPLEMENTATION = MODULE.createFunction("Implementations");
+	public static final DependencyFunction WRAPPERS = MODULE.createFunction("Wrappers");
+	public static final DependencyFunction ARRAY_LIST = IMPLEMENTATION.createSubFunction("ArrayList");
+	public static final DependencyFunction LINKED_LIST = IMPLEMENTATION.createSubFunction("LinkedList");
+	public static final DependencyFunction IMMUTABLE_LIST = IMPLEMENTATION.createSubFunction("ImmutableList");
+	public static final DependencyFunction COPY_ON_WRITE_LIST = IMPLEMENTATION.createSubFunction("CopyOnWriteList");
+
 	@Override
 	public String getModuleName() { return "List"; }
 	@Override
 	protected void loadVariables() {}
 	@Override
 	protected void loadFlags() {
-		if(isModuleEnabled()) addKeyFlag("LIST_MODULE");
-		if(isModuleEnabled("Wrappers")) addKeyFlag("LISTS_FEATURE");
-		boolean implementations = isModuleEnabled("Implementations");
-		if(implementations && isModuleEnabled("ArrayList")) addKeyFlag("ARRAY_LIST_FEATURE");
-		if(implementations && isModuleEnabled("LinkedList")) addKeyFlag("LINKED_LIST_FEATURE");
-		if(implementations && isModuleEnabled("ImmutableList")) addKeyFlag("IMMUTABLE_LIST_FEATURE");
-		if(implementations && isModuleEnabled("CopyOnWriteList")) addKeyFlag("COPY_ON_WRITE_LIST_FEATURE");
+		if(MODULE.isEnabled()) addKeyFlag("LIST_MODULE");
+		if(WRAPPERS.isEnabled()) addKeyFlag("LISTS_FEATURE");
+		if(ARRAY_LIST.isEnabled()) addKeyFlag("ARRAY_LIST_FEATURE");
+		if(LINKED_LIST.isEnabled()) addKeyFlag("LINKED_LIST_FEATURE");
+		if(IMMUTABLE_LIST.isEnabled()) addKeyFlag("IMMUTABLE_LIST_FEATURE");
+		if(COPY_ON_WRITE_LIST.isEnabled()) addKeyFlag("COPY_ON_WRITE_LIST_FEATURE");
 	}
 	
 	@Override
 	protected void loadBlockades()
 	{
-		if(!isModuleEnabled("Wrappers")) addBlockedFiles("Lists");
-		boolean implementations = !isModuleEnabled("Implementations");
-		if(implementations || !isModuleEnabled("ArrayList")) addBlockedFiles("ArrayList");
-		if(implementations || !isModuleEnabled("LinkedList")) addBlockedFiles("LinkedList");
-		if(implementations || !isModuleEnabled("ImmutableList")) addBlockedFiles("ImmutableList");
-		if(implementations || !isModuleEnabled("CopyOnWriteList")) addBlockedFiles("CopyOnWriteList");
-		if(!isModuleEnabled()) addBlockedFiles("List", "AbstractList");
+		if(!WRAPPERS.isEnabled()) addBlockedFiles("Lists");
+		if(!ARRAY_LIST.isEnabled()) addBlockedFiles("ArrayList");
+		if(!LINKED_LIST.isEnabled()) addBlockedFiles("LinkedList");
+		if(!IMMUTABLE_LIST.isEnabled()) addBlockedFiles("ImmutableList");
+		if(!COPY_ON_WRITE_LIST.isEnabled()) addBlockedFiles("CopyOnWriteList");
+		if(!MODULE.isEnabled()) addBlockedFiles("List", "AbstractList");
 		
 		if(keyType.isObject()) addBlockedFiles("ListFillBufferTester");
 		if(keyType == ClassType.BOOLEAN) addBlockedFiles("ListFillBufferTester", "ListReplaceAllTester");
diff --git a/src/builder/java/speiger/src/builder/modules/MapModule.java b/src/builder/java/speiger/src/builder/modules/MapModule.java
index f8a4f0e7..9104dcee 100644
--- a/src/builder/java/speiger/src/builder/modules/MapModule.java
+++ b/src/builder/java/speiger/src/builder/modules/MapModule.java
@@ -5,11 +5,36 @@ import java.util.Set;
 import java.util.TreeSet;
 
 import speiger.src.builder.ClassType;
+import speiger.src.builder.dependency.DependencyFunction;
+import speiger.src.builder.dependency.DependencyModule;
+import speiger.src.builder.dependency.DependencyModule.BiTypeModule;
+import speiger.src.builder.dependency.DependencyType;
+import speiger.src.builder.dependency.DependencyValue;
 
 @SuppressWarnings("javadoc")
 public class MapModule extends BaseModule
 {
 	public static final BaseModule INSTANCE = new MapModule();
+	public static final DependencyModule MODULE = make(new BiTypeModule(INSTANCE), T -> {
+		CollectionModule.MODULE.addChild(new DependencyValue(T));
+		CollectionModule.MODULE.addChild(new DependencyType(T, ClassType.OBJECT));
+		SetModule.MODULE.addChild(T);
+	});
+	public static final DependencyFunction WRAPPERS = MODULE.createFunction("Wrappers");
+	public static final DependencyFunction IMPLEMENTATION = MODULE.createFunction("Implementations");
+	public static final DependencyFunction ORDERED_MAP = MODULE.createFunction("Wrappers");
+	public static final DependencyFunction SORTED_MAP = MODULE.createFunction("Wrappers");
+	public static final DependencyFunction ARRAY_MAP = ORDERED_MAP.addChild(IMPLEMENTATION.createSubFunction("ArrayMap"));
+	public static final DependencyFunction IMMUTABLE_MAP = IMPLEMENTATION.createSubFunction("ImmutableMap");
+	public static final DependencyFunction HASH_MAP = IMPLEMENTATION.createSubFunction("HashMap");
+	public static final DependencyFunction LINKED_MAP = HASH_MAP.addChild(ORDERED_MAP.addChild(IMPLEMENTATION.createSubFunction("LinkedHashMap")));
+	public static final DependencyFunction CUSTOM_MAP = IMPLEMENTATION.createSubFunction("CustomHashMap");
+	public static final DependencyFunction LINKED_CUSTOM_MAP = CUSTOM_MAP.addChild(ORDERED_MAP.addChild(IMPLEMENTATION.createSubFunction("LinkedCustomHashMap")));
+	public static final DependencyFunction ENUM_MAP = IMPLEMENTATION.createSubFunction("EnumMap");
+	public static final DependencyFunction LINKED_ENUM_MAP = ENUM_MAP.addChild(ORDERED_MAP.addChild(IMPLEMENTATION.createSubFunction("LinkedEnumMap")));
+	public static final DependencyFunction CONCURRENT_MAP = IMPLEMENTATION.createSubFunction("ConcurrentMap");
+	public static final DependencyFunction AVL_TREE_MAP = SORTED_MAP.addChild(IMPLEMENTATION.createSubFunction("AVLTreeMap"));
+	public static final DependencyFunction RB_TREE_MAP = SORTED_MAP.addChild(IMPLEMENTATION.createSubFunction("RBTreeMap"));
 	
 	@Override
 	public String getModuleName() { return "Map"; }
@@ -38,61 +63,43 @@ public class MapModule extends BaseModule
 	@Override
 	protected void loadFlags()
 	{
-		if(isModuleEnabled()) addFlag("MAP_MODULE");
-		if(isModuleEnabled("Wrappers")) addFlag("MAPS_FEATURE");
-		boolean implementations = isModuleEnabled("Implementations");
-		boolean hashMap = implementations && isModuleEnabled("HashMap");
-		boolean customHashMap = implementations && isModuleEnabled("CustomHashMap");
-		boolean enumMap = implementations && isModuleEnabled("EnumMap");
+		if(MODULE.isEnabled()) addFlag("MAP_MODULE");
+		if(WRAPPERS.isEnabled()) addFlag("MAPS_FEATURE");
+		if(ORDERED_MAP.isEnabled()) addFlag("ORDERED_MAP_FEATURE");
+		if(ARRAY_MAP.isEnabled()) addFlag("ARRAY_MAP_FEATURE");
+		if(LINKED_MAP.isEnabled()) addFlag("LINKED_MAP_FEATURE");
+		if(LINKED_CUSTOM_MAP.isEnabled()) addFlag("LINKED_CUSTOM_MAP_FEATURE");
+		if(LINKED_ENUM_MAP.isEnabled()) addFlag("LINKED_ENUM_MAP_FEATURE");
 		
-		if(isModuleEnabled("OrderedMap")) {
-			addFlag("ORDERED_MAP_FEATURE");
-			if(isModuleEnabled("ArrayMap")) addFlag("ARRAY_MAP_FEATURE");
-			if(hashMap && isModuleEnabled("LinkedHashMap")) addFlag("LINKED_MAP_FEATURE");
-			if(customHashMap && isModuleEnabled("LinkedCustomHashMap")) addFlag("LINKED_CUSTOM_MAP_FEATURE");
-			if(enumMap && isModuleEnabled("LinkedEnumMap")) addFlag("LINKED_ENUM_MAP_FEATURE");
-		}
-		if(isModuleEnabled("SortedMap")) {
-			addFlag("SORTED_MAP_FEATURE");
-			if(implementations && isModuleEnabled("AVLTreeMap")) addFlag("AVL_TREE_MAP_FEATURE");
-			if(implementations && isModuleEnabled("RBTreeMap")) addFlag("RB_TREE_MAP_FEATURE");
-		}
-		if(implementations && isModuleEnabled("ConcurrentMap")) addFlag("CONCURRENT_MAP_FEATURE");
-		if(implementations && isModuleEnabled("ImmutableMap")) addFlag("IMMUTABLE_MAP_FEATURE");
-		if(hashMap) addFlag("MAP_FEATURE");
-		if(customHashMap) addFlag("CUSTOM_MAP_FEATURE");
-		if(enumMap) addFlag("ENUM_MAP_FEATURE");
+		if(SORTED_MAP.isEnabled()) addFlag("SORTED_MAP_FEATURE");
+		if(AVL_TREE_MAP.isEnabled()) addFlag("AVL_TREE_MAP_FEATURE");
+		if(RB_TREE_MAP.isEnabled()) addFlag("RB_TREE_MAP_FEATURE");
+		
+		if(CONCURRENT_MAP.isEnabled()) addFlag("CONCURRENT_MAP_FEATURE");
+		if(IMMUTABLE_MAP.isEnabled()) addFlag("IMMUTABLE_MAP_FEATURE");
+		if(HASH_MAP.isEnabled()) addFlag("MAP_FEATURE");
+		if(CUSTOM_MAP.isEnabled()) addFlag("CUSTOM_MAP_FEATURE");
+		if(ENUM_MAP.isEnabled()) addFlag("ENUM_MAP_FEATURE");
 	}
 	
 	@Override
 	protected void loadBlockades()
 	{
-		if(!isModuleEnabled()) addBlockedFiles("Map", "AbstractMap");
-		if(!isModuleEnabled("Wrappers")) addBlockedFiles("Maps");
-		boolean implementations = !isModuleEnabled("Implementations");
-		if(implementations || !isModuleEnabled("ImmutableMap")) addBlockedFiles("ImmutableOpenHashMap");
-		if(implementations || !isModuleEnabled("ConcurrentMap")) addBlockedFiles("ConcurrentMap", "ConcurrentOpenHashMap");
-		
-		boolean ordered = !isModuleEnabled("OrderedMap");
-		if(ordered) addBlockedFiles("OrderedMap");
-		boolean hashMap = implementations || !isModuleEnabled("HashMap");
-		if(hashMap) addBlockedFiles("OpenHashMap");
-		if(hashMap || ordered || !isModuleEnabled("LinkedHashMap")) addBlockedFiles("LinkedOpenHashMap");
-		
-		boolean customHashMap = implementations || !isModuleEnabled("CustomHashMap");
-		if(customHashMap) addBlockedFiles("OpenCustomHashMap");
-		if(customHashMap || ordered || !isModuleEnabled("LinkedCustomHashMap")) addBlockedFiles("LinkedOpenCustomHashMap");
-		
-		boolean enumMap = implementations || !isModuleEnabled("EnumMap");
-		if(enumMap) addBlockedFiles("EnumMap");
-		if(enumMap || ordered || !isModuleEnabled("LinkedEnumMap")) addBlockedFiles("LinkedEnumMap");
-		
-		if(ordered || !isModuleEnabled("ArrayMap")) addBlockedFiles("ArrayMap");
-		
-		boolean sorted = !isModuleEnabled("SortedMap");
-		if(sorted) addBlockedFiles("SortedMap", "NavigableMap");
-		if(implementations || sorted || !isModuleEnabled("AVLTreeMap")) addBlockedFiles("AVLTreeMap");
-		if(implementations || sorted || !isModuleEnabled("RBTreeMap")) addBlockedFiles("RBTreeMap");
+		if(!MODULE.isEnabled()) addBlockedFiles("Map", "AbstractMap");
+		if(!WRAPPERS.isEnabled()) addBlockedFiles("Maps");
+		if(!IMMUTABLE_MAP.isEnabled()) addBlockedFiles("ImmutableOpenHashMap");
+		if(!CONCURRENT_MAP.isEnabled()) addBlockedFiles("ConcurrentMap", "ConcurrentOpenHashMap");
+		if(!ORDERED_MAP.isEnabled()) addBlockedFiles("OrderedMap");
+		if(!HASH_MAP.isEnabled()) addBlockedFiles("OpenHashMap");
+		if(!LINKED_MAP.isEnabled()) addBlockedFiles("LinkedOpenHashMap");
+		if(CUSTOM_MAP.isEnabled()) addBlockedFiles("OpenCustomHashMap");
+		if(!LINKED_CUSTOM_MAP.isEnabled()) addBlockedFiles("LinkedOpenCustomHashMap");
+		if(!ENUM_MAP.isEnabled()) addBlockedFiles("EnumMap");
+		if(!LINKED_ENUM_MAP.isEnabled()) addBlockedFiles("LinkedEnumMap");
+		if(!ARRAY_MAP.isEnabled()) addBlockedFiles("ArrayMap");
+		if(!SORTED_MAP.isEnabled()) addBlockedFiles("SortedMap", "NavigableMap");
+		if(!AVL_TREE_MAP.isEnabled()) addBlockedFiles("AVLTreeMap");
+		if(!RB_TREE_MAP.isEnabled()) addBlockedFiles("RBTreeMap");
 		
 		if(keyType == ClassType.BOOLEAN)
 		{
diff --git a/src/builder/java/speiger/src/builder/modules/PairModule.java b/src/builder/java/speiger/src/builder/modules/PairModule.java
index b17efbc7..71fe89a1 100644
--- a/src/builder/java/speiger/src/builder/modules/PairModule.java
+++ b/src/builder/java/speiger/src/builder/modules/PairModule.java
@@ -5,11 +5,18 @@ import java.util.Set;
 import java.util.TreeSet;
 
 import speiger.src.builder.ClassType;
+import speiger.src.builder.dependency.DependencyFunction;
+import speiger.src.builder.dependency.DependencyModule;
+import speiger.src.builder.dependency.DependencyModule.BiTypeModule;
 
 @SuppressWarnings("javadoc")
 public class PairModule extends BaseModule
 {
 	public static final BaseModule INSTANCE = new PairModule();
+	public static final DependencyModule MODULE = new BiTypeModule(INSTANCE);
+	public static final DependencyFunction IMMUTABLE = MODULE.createFunction("Immutable");
+	public static final DependencyFunction MUTABLE = MODULE.createFunction("Mutable");
+	
 	@Override
 	public String getModuleName() { return "Pair"; }
 	@Override
@@ -25,16 +32,16 @@ public class PairModule extends BaseModule
 	
 	@Override
 	protected void loadFlags() {
-		if(isModuleEnabled()) addFlag("PAIR_MODULE");
-		if(isModuleEnabled("Mutable")) addFlag("MUTABLE_PAIR");
-		if(isModuleEnabled("Immutable")) addFlag("IMMUTABLE_PAIR");
+		if(MODULE.isEnabled()) addFlag("PAIR_MODULE");
+		if(MUTABLE.isEnabled()) addFlag("MUTABLE_PAIR");
+		if(IMMUTABLE.isEnabled()) addFlag("IMMUTABLE_PAIR");
 	}
 	
 	@Override
 	protected void loadBlockades() {
-		if(!isModuleEnabled()) addBlockedFiles("Pair");
-		if(!isModuleEnabled("Mutable")) addBlockedFiles("MutablePair");
-		if(!isModuleEnabled("Immutable")) addBlockedFiles("ImmutablePair");
+		if(!MODULE.isEnabled()) addBlockedFiles("Pair");
+		if(!MUTABLE.isEnabled()) addBlockedFiles("MutablePair");
+		if(!IMMUTABLE.isEnabled()) addBlockedFiles("ImmutablePair");
 	}
 	
 	@Override
diff --git a/src/builder/java/speiger/src/builder/modules/PrioQueueModule.java b/src/builder/java/speiger/src/builder/modules/PrioQueueModule.java
index d8cba687..a5917357 100644
--- a/src/builder/java/speiger/src/builder/modules/PrioQueueModule.java
+++ b/src/builder/java/speiger/src/builder/modules/PrioQueueModule.java
@@ -5,11 +5,21 @@ import java.util.Set;
 import java.util.TreeSet;
 
 import speiger.src.builder.ClassType;
+import speiger.src.builder.dependency.DependencyFunction;
+import speiger.src.builder.dependency.DependencyModule;
+import speiger.src.builder.dependency.DependencyModule.SingleTypeModule;
 
 @SuppressWarnings("javadoc")
 public class PrioQueueModule extends BaseModule
 {
 	public static final BaseModule INSTANCE = new PrioQueueModule();
+	public static final DependencyModule MODULE = CollectionModule.MODULE.addChild(new SingleTypeModule(INSTANCE));
+	public static final DependencyFunction IMPLEMENTATION = MODULE.createFunction("Implementations");
+	public static final DependencyFunction WRAPPERS = MODULE.createFunction("Wrappers");
+	public static final DependencyFunction DEQUEUE = MODULE.createFunction("Dequeue");
+	public static final DependencyFunction FIFO_QUEUE = DEQUEUE.addChild(IMPLEMENTATION.createSubFunction("FiFoQueue"));
+	public static final DependencyFunction HEAP_QUEUE = IMPLEMENTATION.createSubFunction("HeapQueue");
+	public static final DependencyFunction ARRAY_PRIO_QUEUE = IMPLEMENTATION.createSubFunction("ArrayPrioQueue");
 	
 	@Override
 	public String getModuleName() { return "PriorityQueue"; }
@@ -27,27 +37,22 @@ public class PrioQueueModule extends BaseModule
 	
 	@Override
 	protected void loadFlags() {
-		if(isModuleEnabled()) addFlag("QUEUE_MODULE");
-		if(isModuleEnabled("Wrappers")) addKeyFlag("QUEUES_FEATURE");
-		boolean implementations = isModuleEnabled("Implementations");
-		if(isModuleEnabled("Dequeue")) {
-			addKeyFlag("DEQUEUE_FEATURE");
-			if(implementations && isModuleEnabled("FiFoQueue")) addKeyFlag("FIFO_QUEUE_FEATURE");
-		}
-		if(implementations && isModuleEnabled("HeapQueue")) addKeyFlag("HEAP_QUEUE_FEATURE");
-		if(implementations && isModuleEnabled("ArrayPrioQueue")) addKeyFlag("ARRAY_QUEUE_FEATURE");
+		if(MODULE.isEnabled()) addFlag("QUEUE_MODULE");
+		if(WRAPPERS.isEnabled()) addKeyFlag("QUEUES_FEATURE");
+		if(DEQUEUE.isEnabled()) addKeyFlag("DEQUEUE_FEATURE");
+		if(FIFO_QUEUE.isEnabled()) addKeyFlag("FIFO_QUEUE_FEATURE");
+		if(HEAP_QUEUE.isEnabled()) addKeyFlag("HEAP_QUEUE_FEATURE");
+		if(ARRAY_PRIO_QUEUE.isEnabled()) addKeyFlag("ARRAY_QUEUE_FEATURE");
 	}
 	
 	@Override
 	protected void loadBlockades() {
-		if(!isModuleEnabled()) addBlockedFiles("PriorityQueue", "AbstractPriorityQueue");
-		if(!isModuleEnabled("Wrappers")) addBlockedFiles("PriorityQueues");
-		boolean implementations = !isModuleEnabled("Implementations");
-		boolean dequeue = !isModuleEnabled("Dequeue");
-		if(dequeue) addBlockedFiles("PriorityDequeue"); 
-		if(dequeue || implementations || !isModuleEnabled("FiFoQueue")) addBlockedFiles("ArrayFIFOQueue");
-		if(implementations || !isModuleEnabled("HeapQueue")) addBlockedFiles("HeapPriorityQueue");
-		if(implementations || !isModuleEnabled("ArrayPrioQueue")) addBlockedFiles("ArrayPriorityQueue");
+		if(!MODULE.isEnabled()) addBlockedFiles("PriorityQueue", "AbstractPriorityQueue");
+		if(!WRAPPERS.isEnabled()) addBlockedFiles("PriorityQueues");
+		if(!DEQUEUE.isEnabled()) addBlockedFiles("PriorityDequeue");
+		if(!FIFO_QUEUE.isEnabled()) addBlockedFiles("ArrayFIFOQueue");
+		if(!HEAP_QUEUE.isEnabled()) addBlockedFiles("HeapPriorityQueue");
+		if(!ARRAY_PRIO_QUEUE.isEnabled()) addBlockedFiles("ArrayPriorityQueue");
 		
 		if(keyType == ClassType.BOOLEAN) {
 			addBlockedFiles("QueueTests");
diff --git a/src/builder/java/speiger/src/builder/modules/SetModule.java b/src/builder/java/speiger/src/builder/modules/SetModule.java
index 1d7bba8c..315a9e13 100644
--- a/src/builder/java/speiger/src/builder/modules/SetModule.java
+++ b/src/builder/java/speiger/src/builder/modules/SetModule.java
@@ -5,11 +5,27 @@ import java.util.Set;
 import java.util.TreeSet;
 
 import speiger.src.builder.ClassType;
+import speiger.src.builder.dependency.DependencyFunction;
+import speiger.src.builder.dependency.DependencyModule;
+import speiger.src.builder.dependency.DependencyModule.SingleTypeModule;
 
 @SuppressWarnings("javadoc")
 public class SetModule extends BaseModule
 {
 	public static final BaseModule INSTANCE = new SetModule();
+	public static final DependencyModule MODULE = CollectionModule.MODULE.addChild(new SingleTypeModule(INSTANCE));
+	public static final DependencyFunction WRAPPERS = MODULE.createFunction("Wrappers");
+	public static final DependencyFunction IMPLEMENTATION = MODULE.createFunction("Implementations");
+	public static final DependencyFunction ORDERED_SET = MODULE.createFunction("Wrappers");
+	public static final DependencyFunction SORTED_SET = MODULE.createFunction("Wrappers");
+	public static final DependencyFunction ARRAY_SET = ORDERED_SET.addChild(IMPLEMENTATION.createSubFunction("ArraySet"));
+	public static final DependencyFunction IMMUTABLE_SET = IMPLEMENTATION.createSubFunction("ImmutableSet");
+	public static final DependencyFunction HASH_SET = IMPLEMENTATION.createSubFunction("HashSet");
+	public static final DependencyFunction LINKED_SET = HASH_SET.addChild(ORDERED_SET.addChild(IMPLEMENTATION.createSubFunction("LinkedHashSet")));
+	public static final DependencyFunction CUSTOM_SET = IMPLEMENTATION.createSubFunction("CustomHashSet");
+	public static final DependencyFunction LINKED_CUSTOM_SET = CUSTOM_SET.addChild(ORDERED_SET.addChild(IMPLEMENTATION.createSubFunction("LinkedCustomHashSet")));
+	public static final DependencyFunction AVL_TREE_SET = SORTED_SET.addChild(IMPLEMENTATION.createSubFunction("AVLTreeSet"));
+	public static final DependencyFunction RB_TREE_SET = SORTED_SET.addChild(IMPLEMENTATION.createSubFunction("RBTreeSet"));
 	
 	@Override
 	public String getModuleName() { return "Set"; }
@@ -35,52 +51,35 @@ public class SetModule extends BaseModule
 	@Override
 	protected void loadFlags()
 	{
-		if(isModuleEnabled()) addFlag("SET_MODULE");
-		if(isModuleEnabled("Wrappers")) addFlag("SETS_FEATURE");
-		boolean implementations = isModuleEnabled("Implementations");
-		boolean hashSet = implementations && isModuleEnabled("HashSet");
-		boolean customHashSet = implementations && isModuleEnabled("CustomHashSet");
-		
-		if(isModuleEnabled("OrderedSet")) {
-			addFlag("ORDERED_SET_FEATURE");
-			if(implementations && isModuleEnabled("ArraySet")) addFlag("ARRAY_SET_FEATURE");
-			if(hashSet && isModuleEnabled("LinkedHashSet")) addFlag("LINKED_SET_FEATURE");
-			if(customHashSet && isModuleEnabled("LinkedCustomHashSet")) addFlag("LINKED_CUSTOM_SET_FEATURE");
-		}
-		if(isModuleEnabled("SortedSet")) {
-			addFlag("SORTED_SET_FEATURE");
-			if(implementations && isModuleEnabled("AVLTreeSet")) addFlag("AVL_TREE_SET_FEATURE");
-			if(implementations && isModuleEnabled("RBTreeSet")) addFlag("RB_TREE_SET_FEATURE");
-		}
-		if(implementations && isModuleEnabled("ImmutableSet")) addFlag("IMMUTABLE_SET_FEATURE");
-		if(hashSet) addFlag("HASH_SET_FEATURE");
-		if(customHashSet) addFlag("CUSTOM_HASH_SET_FEATURE");
+		if(MODULE.isEnabled()) addFlag("SET_MODULE");
+		if(WRAPPERS.isEnabled()) addFlag("SETS_FEATURE");
+		if(ORDERED_SET.isEnabled()) addFlag("ORDERED_SET_FEATURE");
+		if(SORTED_SET.isEnabled()) addFlag("SORTED_SET_FEATURE");
+		if(IMMUTABLE_SET.isEnabled()) addFlag("IMMUTABLE_SET_FEATURE");
+		if(ARRAY_SET.isEnabled()) addFlag("ARRAY_SET_FEATURE");
+		if(HASH_SET.isEnabled()) addFlag("HASH_SET_FEATURE");
+		if(LINKED_SET.isEnabled()) addFlag("LINKED_SET_FEATURE");
+		if(CUSTOM_SET.isEnabled()) addFlag("CUSTOM_HASH_SET_FEATURE");
+		if(LINKED_CUSTOM_SET.isEnabled()) addFlag("LINKED_CUSTOM_SET_FEATURE");
+		if(AVL_TREE_SET.isEnabled()) addFlag("AVL_TREE_SET_FEATURE");
+		if(RB_TREE_SET.isEnabled()) addFlag("RB_TREE_SET_FEATURE");
 	}
 	
 	@Override
 	protected void loadBlockades()
 	{
-		if(!isModuleEnabled()) addBlockedFiles("Set", "AbstractSet");
-		if(!isModuleEnabled("Wrappers")) addBlockedFiles("Sets");
-		boolean implementations = !isModuleEnabled("Implementations");
-		if(implementations || !isModuleEnabled("ImmutableSet")) addBlockedFiles("ImmutableOpenHashSet");
-		
-		boolean ordered = !isModuleEnabled("OrderedSet");
-		if(ordered) addBlockedFiles("OrderedSet");
-		boolean hashSet = implementations || !isModuleEnabled("HashSet");
-		if(hashSet) addBlockedFiles("OpenHashSet");
-		if(hashSet || ordered || !isModuleEnabled("LinkedHashSet")) addBlockedFiles("LinkedOpenHashSet");
-		
-		boolean customHashSet = implementations || !isModuleEnabled("CustomHashSet");
-		if(customHashSet) addBlockedFiles("OpenCustomHashSet");
-		if(customHashSet || ordered || !isModuleEnabled("LinkedCustomHashSet")) addBlockedFiles("LinkedOpenCustomHashSet");
-		
-		if(implementations || ordered || !isModuleEnabled("ArraySet")) addBlockedFiles("ArraySet");
-		
-		boolean sorted = !isModuleEnabled("SortedSet");
-		if(sorted) addBlockedFiles("SortedSet", "NavigableSet");
-		if(implementations || sorted || !isModuleEnabled("AVLTreeSet")) addBlockedFiles("AVLTreeSet");
-		if(implementations || sorted || !isModuleEnabled("RBTreeSet")) addBlockedFiles("RBTreeSet");
+		if(!MODULE.isEnabled()) addBlockedFiles("Set", "AbstractSet");
+		if(!WRAPPERS.isEnabled()) addBlockedFiles("Sets");
+		if(!IMMUTABLE_SET.isEnabled()) addBlockedFiles("ImmutableOpenHashSet");
+		if(!ORDERED_SET.isEnabled()) addBlockedFiles("OrderedSet");
+		if(!HASH_SET.isEnabled()) addBlockedFiles("OpenHashSet");
+		if(!LINKED_SET.isEnabled()) addBlockedFiles("LinkedOpenHashSet");
+		if(!CUSTOM_SET.isEnabled()) addBlockedFiles("OpenCustomHashSet");
+		if(!LINKED_CUSTOM_SET.isEnabled()) addBlockedFiles("LinkedOpenCustomHashSet");
+		if(!ARRAY_SET.isEnabled()) addBlockedFiles("ArraySet");
+		if(!SORTED_SET.isEnabled()) addBlockedFiles("SortedSet", "NavigableSet");
+		if(!AVL_TREE_SET.isEnabled()) addBlockedFiles("AVLTreeSet");
+		if(!RB_TREE_SET.isEnabled()) addBlockedFiles("RBTreeSet");
 		
 		if(keyType == ClassType.BOOLEAN)
 		{