diff --git a/feedbackloop.execute/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/execute/ExecuteImplTest.java b/feedbackloop.execute/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/execute/ExecuteImplTest.java
index 66823f1459c45fccc007815b3004527b62159be6..f3f79ac72847b1c8c251c96a6d011014479f7115 100644
--- a/feedbackloop.execute/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/execute/ExecuteImplTest.java
+++ b/feedbackloop.execute/src/test/java/de/tudresden/inf/st/eraser/feedbackloop/execute/ExecuteImplTest.java
@@ -21,7 +21,7 @@ public class ExecuteImplTest {
   @Test
   public void testColorControlledByOneNumber() {
     ModelAndItem mai = TestUtils.createModelAndItem(0);
-    Root model = mai.model;
+    OpenHAB2Model model = mai.model;
     NumberItem numberItem = mai.item;
 
     ColorItem lamp = new ColorItem();
@@ -33,7 +33,7 @@ public class ExecuteImplTest {
     numberItem.addControlling(lamp);
 
     Execute execute = new ExecuteImpl();
-    execute.setKnowledgeBase(model);
+    execute.setKnowledgeBase(model.getRoot());
 
     Assert.assertEquals(0, numberItem.getState(), DELTA);
     Assert.assertEquals(TupleHSB.of(0, 0, 0), lamp.getState());
@@ -47,7 +47,7 @@ public class ExecuteImplTest {
 
   @Test
   public void testColorControlledByOneBoolean() {
-    Root model = TestUtils.createModelAndItem(0).model;
+    OpenHAB2Model model = TestUtils.createModelAndItem(0).model;
 
     ItemWithBooleanState button = new SwitchItem();
     button.setID("button");
@@ -64,7 +64,7 @@ public class ExecuteImplTest {
     button.addControlling(lamp);
 
     Execute execute = new ExecuteImpl();
-    execute.setKnowledgeBase(model);
+    execute.setKnowledgeBase(model.getRoot());
 
     Assert.assertFalse(button.getState());
     Assert.assertEquals(TupleHSB.of(0, 0, 0), lamp.getState());
@@ -79,7 +79,7 @@ public class ExecuteImplTest {
   @Test
   public void testColorControlledByMany() {
     ModelAndItem mai = TestUtils.createModelAndItem(0);
-    Root model = mai.model;
+    OpenHAB2Model model = mai.model;
     NumberItem numberItem = mai.item;
 
     Group g = TestUtils.getDefaultGroup(model);
@@ -108,7 +108,7 @@ public class ExecuteImplTest {
     lamp.addControlledBy(colorItem);
 
     Execute execute = new ExecuteImpl();
-    execute.setKnowledgeBase(model);
+    execute.setKnowledgeBase(model.getRoot());
 
     Assert.assertEquals(0, numberItem.getState(), DELTA);
     Assert.assertEquals("0", stringItem.getState());
diff --git a/integration/src/main/java/de/tudresden/inf/st/eraser/integration/IntegrationMain.java b/integration/src/main/java/de/tudresden/inf/st/eraser/integration/IntegrationMain.java
index a7ca2904072ea46e0a0243fd7bc47328729a55c4..1909ccea5a27fe1e2e33ebd6a42756457a8c6f55 100644
--- a/integration/src/main/java/de/tudresden/inf/st/eraser/integration/IntegrationMain.java
+++ b/integration/src/main/java/de/tudresden/inf/st/eraser/integration/IntegrationMain.java
@@ -79,7 +79,7 @@ public class IntegrationMain {
       logger.info("Start!");
       Root model = Main.importFromFile();
 //      Root model = importFromLocalFile();
-      logger.debug("Got model: {}", model.description());
+      logger.debug("Got model: {}", model.getOpenHAB2Model().description());
       MqttRoot mqttRoot = new MqttRoot();
       mqttRoot.setHostByName("localhost");
       mqttRoot.setIncomingPrefix("oh2/out/");
@@ -89,7 +89,7 @@ public class IntegrationMain {
       irisStateTopic.setPart("state");
       irisTopic.addSubTopic(irisStateTopic);
       Item iris = null;
-      for (Item item : model.items()) {
+      for (Item item : model.getOpenHAB2Model().items()) {
         if (item.getID().equals("iris1_item")) {
           iris = item;
           break;
diff --git a/ml_test/src/main/java/de/tudresden/inf/st/eraser/ml_test/Main.java b/ml_test/src/main/java/de/tudresden/inf/st/eraser/ml_test/Main.java
index d17b6c97dc647e9faebfb1fd1ca9b4450fef4725..59c156853782b8e58010d24393e7c14c73ffefb8 100644
--- a/ml_test/src/main/java/de/tudresden/inf/st/eraser/ml_test/Main.java
+++ b/ml_test/src/main/java/de/tudresden/inf/st/eraser/ml_test/Main.java
@@ -23,15 +23,15 @@ public class Main {
   }
 
   private static Root createModel() {
-    Root model = Root.createEmptyRoot();
+    Root root = Root.createEmptyRoot();
     Group group = new Group();
     group.setID("Group1");
-    model.addGroup(group);
+    root.getOpenHAB2Model().addGroup(group);
     Item activityItem = newItem("activity", "Recognized activity", false, 8);
     Item brightnessItem = newItem("brightness", "Measured brightness", false, 5);
     group.addItem(activityItem);
     group.addItem(brightnessItem);
-    return model;
+    return root;
   }
 
   private static NumberItem newItem(String id, String label, boolean defaultSendState, int initialState) {
@@ -70,7 +70,7 @@ public class Main {
       }
     }
     logger.info("Classification results: {}", results);
-    logger.info("Took {}ms", String.join("ms, ", times.stream().map(l -> Long.toString(l)).collect(Collectors.toList())));
+    logger.info("Took {}ms", times.stream().map(l -> Long.toString(l)).collect(Collectors.joining("ms, ")));
     logger.info("Took on average: {}ms",
         Arrays.stream(times.toArray(new Long[0])).mapToLong(l -> l).average().orElse(-1));
     logger.info("Took on median: {}ms",
@@ -78,30 +78,36 @@ public class Main {
             .skip((REPETITIONS-1)/2).limit(2-REPETITIONS%2).average().orElse(Double.NaN));
   }
 
-  /**
-   * Purpose: Create a neural network with 3 layers (2 + 10 + 1 neurons)
-   * Sigmoid function for all layers, combinator of output is identity function
-   */
-  private static void createAndTestBrightnessNetwork() {
-    /*
-   	- Helligkeit NN:
-      - arbeitet momentan mit Zonen und nicht mit einzelnen Lampen
-      - 3 Layers
-      - Input Layer hat Neuronen (Aktivitätsnummer, Wert vom Helligkeitssensor)
-      - Hidden Layer hat 10 Neuronen
-      - Output Layer hat 1 Neuron ( Helligkeitswert)
-      - Aktivierungsfunktion: Sigmoidfunktion <- selbe für alle Layers
-     */
-    Root model = createModel();
-    Item activityItem = model.resolveItem("activity").orElseThrow(
+  private static class PreparationResult {
+    OutputLayer outputLayer;
+    DoubleArrayDoubleFunction sigmoid;
+    InputNeuron activity;
+    InputNeuron brightness;
+    NeuralNetworkRoot nn;
+    HiddenNeuron[] hiddenNeurons;
+
+    PreparationResult(OutputLayer outputLayer, DoubleArrayDoubleFunction sigmoid, InputNeuron activity,
+                      InputNeuron brightness, NeuralNetworkRoot nn, HiddenNeuron[] hiddenNeurons) {
+      this.outputLayer = outputLayer;
+      this.sigmoid = sigmoid;
+      this.activity = activity;
+      this.brightness = brightness;
+      this.nn = nn;
+      this.hiddenNeurons = hiddenNeurons;
+    }
+  }
+
+  private static PreparationResult prepareNetwork() {
+    Root root = createModel();
+    Item activityItem = root.getOpenHAB2Model().resolveItem("activity").orElseThrow(
         () -> new RuntimeException("Activity not found"));
-    Item brightnessItem = model.resolveItem("brightness").orElseThrow(
+    Item brightnessItem = root.getOpenHAB2Model().resolveItem("brightness").orElseThrow(
         () -> new RuntimeException("Brightness not found"));
     NeuralNetworkRoot nn = new NeuralNetworkRoot();
 
     DoubleArrayDoubleFunction sigmoid = inputs -> Math.signum(Arrays.stream(inputs).sum());
 
-    // input layer
+    // input layer (2 neurons)
     InputNeuron activity = new InputNeuron();
     activity.setItem(activityItem);
     InputNeuron brightness = new InputNeuron();
@@ -109,31 +115,50 @@ public class Main {
     nn.addInputNeuron(activity);
     nn.addInputNeuron(brightness);
 
-    // output layer
     OutputLayer outputLayer = new OutputLayer();
-    OutputNeuron output = new OutputNeuron();
-    output.setLabel("Brightness_Output");
-    output.setActivationFormula(sigmoid);
-    outputLayer.addOutputNeuron(output);
-    // we just have one output neuron, thus use IdentityFunction
-    outputLayer.setCombinator(inputs -> inputs[0]);
     nn.setOutputLayer(outputLayer);
 
-    // hidden layer
+    // hidden layer (10 neurons)
     HiddenNeuron[] hiddenNeurons = new HiddenNeuron[10];
-    for (int i = 0; i < hiddenNeurons.length; i++) {
+    for (int hiddenIndex = 0; hiddenIndex < hiddenNeurons.length; hiddenIndex++) {
       HiddenNeuron hiddenNeuron = new HiddenNeuron();
       hiddenNeuron.setActivationFormula(sigmoid);
-      hiddenNeurons[i] = hiddenNeuron;
       nn.addHiddenNeuron(hiddenNeuron);
       activity.connectTo(hiddenNeuron, 1.0/2.0);
       brightness.connectTo(hiddenNeuron, 1.0/2.0);
-      hiddenNeuron.connectTo(output, 1.0/hiddenNeurons.length);
     }
+    root.getMachineLearningRoot().setPreferenceLearning(nn);
 
-    model.getMachineLearningRoot().setPreferenceLearning(nn);
+    return new PreparationResult(outputLayer, sigmoid, activity, brightness, nn, hiddenNeurons);
+  }
 
-    classifyTimed(nn, NeuralNetworkRoot::classify,
+  /**
+   * Purpose: Create a neural network with 3 layers (2 + 10 + 1 neurons)
+   * Sigmoid function for all layers, combinator of output is identity function
+   */
+  private static void createAndTestBrightnessNetwork() {
+    /*
+   	- Helligkeit NN:
+      - arbeitet momentan mit Zonen und nicht mit einzelnen Lampen
+      - 3 Layers
+      - Input Layer hat Neuronen (Aktivitätsnummer, Wert vom Helligkeitssensor)
+      - Hidden Layer hat 10 Neuronen
+      - Output Layer hat 1 Neuron ( Helligkeitswert)
+      - Aktivierungsfunktion: Sigmoidfunktion <- selbe für alle Layers
+     */
+    PreparationResult pr = prepareNetwork();
+    OutputNeuron output = new OutputNeuron();
+    output.setLabel("Brightness_Output");
+    output.setActivationFormula(pr.sigmoid);
+    pr.outputLayer.addOutputNeuron(output);
+    // we just have one output neuron, thus use IdentityFunction
+    pr.outputLayer.setCombinator(inputs -> inputs[0]);
+
+    for (HiddenNeuron hiddenNeuron : pr.hiddenNeurons) {
+      hiddenNeuron.connectTo(output, 1.0/pr.hiddenNeurons.length);
+    }
+
+    classifyTimed(pr.nn, NeuralNetworkRoot::classify,
         classification -> Double.toString(classification.number));
   }
 
@@ -142,52 +167,23 @@ public class Main {
    * Sigmoid function for all layers, combinator creates RGB value in hex form
    */
   private static void createAndTestColorNetwork() {
-    Root model = createModel();
-    Item activityItem = model.resolveItem("activity").orElseThrow(
-        () -> new RuntimeException("Activity not found"));
-    Item brightnessItem = model.resolveItem("brightness").orElseThrow(
-        () -> new RuntimeException("Brightness not found"));
-    NeuralNetworkRoot nn = new NeuralNetworkRoot();
-
-    DoubleArrayDoubleFunction sigmoid = inputs -> Math.signum(Arrays.stream(inputs).sum());
-
-    // input layer (2 neurons)
-    InputNeuron activity = new InputNeuron();
-    activity.setItem(activityItem);
-    InputNeuron brightness = new InputNeuron();
-    brightness.setItem(brightnessItem);
-    nn.addInputNeuron(activity);
-    nn.addInputNeuron(brightness);
-
-    // output layer (3 neurons)
-    OutputLayer outputLayer = new OutputLayer();
+    PreparationResult pr = prepareNetwork();
     for (int i = 0; i < 3; i++) {
       OutputNeuron output = new OutputNeuron();
       output.setLabel("Brightness_Output_" + i);
       output.setActivationFormula(inputs -> Arrays.stream(inputs).sum());
-      outputLayer.addOutputNeuron(output);
+      pr.outputLayer.addOutputNeuron(output);
     }
     // we have three output neurons, combine them to a double value (representing RGB)
-    outputLayer.setCombinator(inputs -> 65536 * Math.ceil(255.0 * inputs[0]) + 256 * Math.ceil(255.0 * inputs[1]) + Math.ceil(255.0 * inputs[0]));
-    nn.setOutputLayer(outputLayer);
+    pr.outputLayer.setCombinator(inputs -> 65536 * Math.ceil(255.0 * inputs[0]) + 256 * Math.ceil(255.0 * inputs[1]) + Math.ceil(255.0 * inputs[0]));
 
-    // hidden layer (10 neurons)
-    HiddenNeuron[] hiddenNeurons = new HiddenNeuron[10];
-    for (int hiddenIndex = 0; hiddenIndex < hiddenNeurons.length; hiddenIndex++) {
-      HiddenNeuron hiddenNeuron = new HiddenNeuron();
-      hiddenNeuron.setActivationFormula(sigmoid);
-      hiddenNeurons[hiddenIndex] = hiddenNeuron;
-      nn.addHiddenNeuron(hiddenNeuron);
-      activity.connectTo(hiddenNeuron, 1.0/2.0);
-      brightness.connectTo(hiddenNeuron, 1.0/2.0);
-      for (int outputIndex = 0; outputIndex < outputLayer.getNumOutputNeuron(); outputIndex++) {
-        hiddenNeuron.connectTo(outputLayer.getOutputNeuron(outputIndex), random.nextDouble() * 1.0/hiddenNeurons.length);
+    for (HiddenNeuron hiddenNeuron : pr.hiddenNeurons) {
+      for (int outputIndex = 0; outputIndex < pr.outputLayer.getNumOutputNeuron(); outputIndex++) {
+        hiddenNeuron.connectTo(pr.outputLayer.getOutputNeuron(outputIndex), random.nextDouble() * 1.0/pr.hiddenNeurons.length);
       }
     }
 
-    model.getMachineLearningRoot().setPreferenceLearning(nn);
-
-    classifyTimed(nn, NeuralNetworkRoot::classify,
+    classifyTimed(pr.nn, NeuralNetworkRoot::classify,
         classification -> Double.toHexString(classification.number));
 
 //    long before = System.nanoTime();
diff --git a/skywriter-hue-integration/src/main/java/de/tudresden/inf/st/eraser/skywriter_hue_integration/Main.java b/skywriter-hue-integration/src/main/java/de/tudresden/inf/st/eraser/skywriter_hue_integration/Main.java
index f6769cb625d1b914f54f6f377500166e61c1f9a9..3f64c8cdd3c530d8a287a0d3ce0d140f449c5921 100644
--- a/skywriter-hue-integration/src/main/java/de/tudresden/inf/st/eraser/skywriter_hue_integration/Main.java
+++ b/skywriter-hue-integration/src/main/java/de/tudresden/inf/st/eraser/skywriter_hue_integration/Main.java
@@ -3,10 +3,7 @@ package de.tudresden.inf.st.eraser.skywriter_hue_integration;
 import beaver.Parser;
 import de.tudresden.inf.st.eraser.commons.color.ColorUtils;
 import de.tudresden.inf.st.eraser.commons.color.ColorUtils.RGBvalues;
-import de.tudresden.inf.st.eraser.jastadd.model.Item;
-import de.tudresden.inf.st.eraser.jastadd.model.Root;
-import de.tudresden.inf.st.eraser.jastadd.model.Rule;
-import de.tudresden.inf.st.eraser.jastadd.model.SetStateFromItemsAction;
+import de.tudresden.inf.st.eraser.jastadd.model.*;
 import de.tudresden.inf.st.eraser.openhab2.mqtt.MQTTUpdater;
 import de.tudresden.inf.st.eraser.util.ParserUtils;
 import org.apache.logging.log4j.LogManager;
@@ -39,7 +36,8 @@ public class Main {
   @SuppressWarnings("ResultOfMethodCallIgnored")
   public static void main(String[] args) throws IOException, Parser.Exception {
     // use openHAB-eraser-connection to update hue (automatically done)
-    Root model = ParserUtils.load("skywriter-hue.eraser", Main.class);
+    Root root = ParserUtils.load("skywriter-hue.eraser", Main.class);
+    OpenHAB2Model model = root.getOpenHAB2Model();
     Item irisItem = model.resolveItem("iris1_item").orElseThrow(() ->
         new NoSuchElementException("Iris1_item not found"));
     Item skywriter1_x = model.resolveItem("skywriter1_x").orElseThrow(() ->
@@ -48,10 +46,10 @@ public class Main {
         new NoSuchElementException("Skywriter1 y not found"));
     Item skywriter1_xyz = model.resolveItem("skywriter1_xyz").orElseThrow(() ->
         new NoSuchElementException("Skywriter1 xyz not found"));
-    System.out.println(model.prettyPrint());
+    System.out.println(root.prettyPrint());
     // define rule to switch color, based on xyz-to-rgb-to-hsb mapping
     Rule mapXYtoIrisState = new Rule();
-    model.addRule(mapXYtoIrisState);
+    root.addRule(mapXYtoIrisState);
     mapXYtoIrisState.activateFor(skywriter1_xyz);
 //    mapXYtoIrisState.addEventFor(skywriter1_y, "y changed");
     SetStateFromItemsAction action = new SetStateFromItemsAction();
@@ -64,7 +62,7 @@ public class Main {
     Lock abortLock = new ReentrantLock();
     Condition abortCondition = abortLock.newCondition();
     Thread readFromOpenHABThread = new Thread(() -> {
-      try (MQTTUpdater updater = new MQTTUpdater(model)) {
+      try (MQTTUpdater updater = new MQTTUpdater(root)) {
         updater.start();
         if (!updater.waitUntilReady(3, TimeUnit.SECONDS)) {
           logger.error("openHAB reader not ready. Aborting.");
@@ -84,7 +82,7 @@ public class Main {
       }
     });
     if (USE_READ_FROM_OPENHAB || SEND_TO_OPENHAB) {
-      model.getMqttRoot().setHostByName(MQTT_HOST);
+      root.getMqttRoot().setHostByName(MQTT_HOST);
     }
     if (USE_READ_FROM_OPENHAB) {
       readFromOpenHABThread.start();
@@ -124,7 +122,7 @@ public class Main {
     }
 
     // wait for user to press enter
-    System.out.println("Press [Enter] to quit updating the model.");
+    System.out.println("Press [Enter] to quit updating the root.");
     System.in.read();
 
     // and then cancel the threads