diff --git a/src/main/jastadd/flatter/rewrites/ServiceRewrites.jadd b/src/main/jastadd/flatter/rewrites/ServiceRewrites.jadd
index e66998cb1d6e68ed89df81dd312529d4a578dc04..1409454705c307531bb2e4c003a4f3b1c8a0ba42 100644
--- a/src/main/jastadd/flatter/rewrites/ServiceRewrites.jadd
+++ b/src/main/jastadd/flatter/rewrites/ServiceRewrites.jadd
@@ -25,7 +25,7 @@ aspect ServiceRewrites {
               }
 
               de.tudresden.inf.st.pnml.flatter.transform.ToolspecificsTransformer
-                    .updateServiceTransitionToolspecifics(petriNet(), serverCapacity, this);
+                    .updateTransitionToolspecifics(petriNet(), serverCapacity, this);
 
               Page containerPage = new Page();
               containerPage.setId(this.getId() + "-" + PnmlConstants.PAGE_SERVER_CONTAINER_SUFFIX);
diff --git a/src/main/jastadd/flatter/rewrites/TopicRewrites.jadd b/src/main/jastadd/flatter/rewrites/TopicRewrites.jadd
index ab6613b587b4530e486e3b0ff0e80edf871424f9..26d9266e16f34ebfe7e97344d796843adcb6bf64 100644
--- a/src/main/jastadd/flatter/rewrites/TopicRewrites.jadd
+++ b/src/main/jastadd/flatter/rewrites/TopicRewrites.jadd
@@ -1,3 +1,89 @@
+import de.tudresden.inf.st.pnml.flatter.template.*;
+import de.tudresden.inf.st.pnml.flatter.transform.*;
+
 aspect TopicRewrites {
 
+    rewrite DinerosTransition {
+    when ( getStaticTransitionInformation().isTopicTransitionInformation() )
+        to Page {
+
+            Page res = new Page();
+            TopicTransitionInformation tti = this.getStaticTransitionInformation().asTopicTransitionInformation();
+
+            // apply rule T1
+            DinerosPlace pTopic = PrimitiveTemplates.getDinerosPlace();
+            pTopic.setId(TemplateConstants.CHANNEL_TOPIC_PLACE + "-" + tti.getTopic());
+
+            PlaceInformation pi = new PlaceInformation();
+            pi.setSubNet("channel");
+            pi.setNode("channel");
+            pTopic.setMutablePlaceInformation(pi);
+            pTopic.getInitialMarking().setText(0);
+            Name pName = new Name();
+            pName.setText(TemplateConstants.CHANNEL_TOPIC_PLACE + "-" + tti.getTopic());
+            pTopic.setName(pName);
+            res.addObject(pTopic);
+
+            DinerosTransition tTopic = PrimitiveTemplates.getDinerosTransition();
+            tTopic.setId(TemplateConstants.CHANNEL_TOPIC_TRANSITION + "-" + tti.getTopic());
+
+            SignalTransitionInformation sti = new SignalTransitionInformation();
+            sti.setSubNet("channel");
+            sti.setNode("channel");
+            Name tName = new Name();
+            tName.setText(TemplateConstants.CHANNEL_TOPIC_TRANSITION + "-" + tti.getTopic());
+            tTopic.setName(tName);
+            res.addObject(tTopic);
+
+            TransformationUtils.createAndIncludeArc(res, pTopic.getId() + "-to-" + tTopic.getId(), pTopic, tTopic);
+
+            // apply rule T2
+            int i = 0;
+            for(PublisherPort pp : tti.getPublisherPorts()){
+                Map<String, Node> pubMap = new HashMap<>();
+                pubMap.put(TemplateConstants.PLACE_TOPIC_PUBLISHER_REF + "-" + tti.getTopic() + "-" + i, petriNet().getPlaceById(pp.getPlaceId()));
+                pubMap.put(TemplateConstants.PLACE_TOPIC_PUBLISHER_CHANNEL_REF + "-" + tti.getTopic() + "-" + i, pTopic);
+                PetriNet pubNet = TopicTemplates.getTopicPublisherPetriNet("-" + tti.getTopic() + "-" + i, pp.getLimit());
+                TransformationUtils.includeTemplateInstance(res, petriNet(), pubNet, "channel", "channel", pubMap);
+                i++;
+            }
+
+            // create node to port mapping as prep for T3 und T4
+            Map<String, List<SubscriberPort>> nodePortMap = new HashMap<>();
+            for(SubscriberPort sp : tti.getSubscriberPorts()){
+                String node = petriNet().getPlaceById(sp.getPlaceId()).asDinerosPlace().getStaticPlaceInformation().getNode();
+                if(nodePortMap.containsKey(node)){
+                    nodePortMap.get(node).add(sp);
+                } else {
+                    List<SubscriberPort> portList = new ArrayList<>();
+                    portList.add(sp);
+                    nodePortMap.put(node, portList);
+                }
+            }
+
+            // apply rule T3
+            int j = 0;
+            for(Map.Entry<String, List<SubscriberPort>> entry : nodePortMap.entrySet()){
+                Map<String, Node> dispatchMap = new HashMap<>();
+                dispatchMap.put(TemplateConstants.TRANSITION_TOPIC_DISPATCHER_CHANNEL_REF + "-" + tti.getTopic() + "-" + j, tTopic);
+                // TODO: make capacity configurable
+                PetriNet dispatchNet = TopicTemplates.getTopicDispatcherPetriNet(tti.getTopic() + "-" + j, 16);
+                TransformationUtils.includeTemplateInstance(res, petriNet(), dispatchNet, "channel", "channel", dispatchMap);
+
+                // apply rule T4
+                int k = 0;
+                for(SubscriberPort sp : tti.getSubscriberPorts()){
+                    Map<String, Node> subMap = new HashMap<>();
+                    subMap.put(TemplateConstants.PLACE_TOPIC_CALLBACK_REF + "-" + tti.getTopic() + "-" + j + "-" + k, petriNet().getPlaceById(sp.getPlaceId()));
+                    subMap.put(TemplateConstants.TRANSITION_TOPIC_CALLBACK_INPUT_REF + "-" + tti.getTopic() + "-" + j + "-" + k,
+                    petriNet().getPlaceById(TemplateConstants.DISPATCHER_OUTPUT_TRANSITION + "-" + tti.getTopic() + "-" + j));
+                    PetriNet callbackNet = TopicTemplates.getTopicCallbackQueuePetriNet(tti.getTopic() + "-" + j + "-" + k, sp.getLimit());
+                    TransformationUtils.includeTemplateInstance(res, petriNet(), callbackNet, "channel", "channel", subMap);
+                    k++;
+                }
+                j++;
+            }
+            return res;
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TemplateConstants.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TemplateConstants.java
index cc4f7ce05962acf6fc17b6e6be1298bde8331fbc..bd2eeaa2621375ffe3d743cf485de57a992a750e 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TemplateConstants.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TemplateConstants.java
@@ -8,6 +8,11 @@ public final class TemplateConstants {
     public static final String PUBLISHER_INPUT_TRANSITION = "PublisherInputTransition";
     public static final String PUBLISHER_OVERFLOW_TRANSITION = "PublisherOverflowTransition";
     public static final String PUBLISHER_OUTPUT_TRANSITION = "PublisherOutputTransition";
+    public static final String PLACE_TOPIC_PUBLISHER_REF = "PublisherPlaceRef";
+    public static final String PLACE_TOPIC_PUBLISHER_CHANNEL_REF = "PublisherChannelPlaceRef";
+    public static final String TRANSITION_TOPIC_DISPATCHER_CHANNEL_REF = "DispatcherChannelTransitionRef";
+    public static final String PLACE_TOPIC_CALLBACK_REF = "CallbackRefPlace";
+    public static final String TRANSITION_TOPIC_CALLBACK_INPUT_REF = "CallbackInputRefTransition";
 
     // topic dispatcher
     public static final String DISPATCHER_INPUT_TRANSITION = "DispatcherInputTransition";
@@ -30,8 +35,8 @@ public final class TemplateConstants {
     public static final String SERVICE_QUEUE_TEMPLATE_PAGE = "ServiceQueueTemplatePage";
 
     // channel elements
-    public static final String CHANNEL_CONNECTOR_PLACE = "ChannelConnectorPlace";
-    public static final String CHANNEL_CONNECTOR_TRANSITION = "ChannelConnectorTransition";
+    public static final String CHANNEL_TOPIC_PLACE = "ChannelConnectorPlace";
+    public static final String CHANNEL_TOPIC_TRANSITION = "ChannelConnectorTransition";
 
     // signal elements
     public static final String INPUT_SIGNAL_TEMPLATE_PAGE = "InputSignalTemplatePage";
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ChannelFlatter.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ChannelFlatter.java
deleted file mode 100644
index 14141ab5855a7411828ce3ae26831046fdf8bc3a..0000000000000000000000000000000000000000
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ChannelFlatter.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package de.tudresden.inf.st.pnml.flatter.transform;
-
-import de.tudresden.inf.st.pnml.jastadd.model.*;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.*;
-
-/**
- * only works if pages / references got flatted before
- */
-public class ChannelFlatter extends Flatter {
-
-    private static final Logger logger = LoggerFactory.getLogger(ChannelFlatter.class);
-
-    private static Set<Arc> getInnerSubnetArcs(PetriNet petriNet, String subnet) {
-
-        Set<Arc> arcs = new HashSet<>();
-
-        for (Arc a : petriNet.allArcs()) {
-
-            if (a.getTarget().isTransitionNode() && a.getSource().isPlaceNode()) {
-
-                if (a.getTarget().asTransitionNode().asTransition().asDinerosTransition().getStaticTransitionInformation().getSubNet().equals(subnet) &&
-                        a.getSource().asPlaceNode().asPlace().asDinerosPlace().getStaticPlaceInformation().getSubNet().equals(subnet)) {
-                    arcs.add(a);
-                }
-            } else {
-                if (a.getSource().asTransitionNode().asTransition().asDinerosTransition().getStaticTransitionInformation().getSubNet().equals(subnet) &&
-                        a.getTarget().asPlaceNode().asPlace().asDinerosPlace().getStaticPlaceInformation().getSubNet().equals(subnet)) {
-                    arcs.add(a);
-                }
-            }
-        }
-
-        return arcs;
-    }
-
-    private static Set<Arc> getSubnetArcs(PetriNet petriNet, String subnet) {
-
-        Set<Arc> arcs = new HashSet<>();
-
-        for (Arc a : petriNet.allArcs()) {
-            if (getArcTargetSubnet(a).equals(subnet) && getArcSourceSubnet(a).equals(subnet)) {
-                arcs.add(a);
-            } else if (getArcSourceSubnet(a).equals(subnet) && !getArcTargetSubnet(a).equals(subnet)) {
-                arcs.add(a);
-            }
-        }
-
-        return arcs;
-    }
-
-    private static String getArcTargetSubnet(Arc arc) {
-
-        if (arc.getTarget().isTransitionNode()) {
-            return arc.getTarget().asTransitionNode().asTransition().asDinerosTransition().getStaticTransitionInformation().getSubNet();
-        } else {
-            return arc.getTarget().asPlaceNode().asPlace().asDinerosPlace().getStaticPlaceInformation().getSubNet();
-        }
-    }
-
-    private static String getArcSourceSubnet(Arc arc) {
-
-        if (arc.getSource().isTransitionNode()) {
-            return arc.getSource().asTransitionNode().asTransition().asDinerosTransition().getStaticTransitionInformation().getSubNet();
-        } else {
-            return arc.getSource().asPlaceNode().asPlace().asDinerosPlace().getStaticPlaceInformation().getSubNet();
-        }
-    }
-
-    private static void getObjectsBySubnet(PetriNet petriNet, String subnet, Set<Place> serverPlaces,
-                                           Set<Transition> serverTransitions, Set<RefPlace> serverRefPlaces, Set<RefTransition> serverRefTransitions) {
-
-        for (Transition t : petriNet.allTransitions()) {
-            if (t.asDinerosTransition().getStaticTransitionInformation().getSubNet().equals(subnet)) {
-                serverTransitions.add(t);
-            }
-        }
-
-        for (Place p : petriNet.allPlaces()) {
-            if (p.asDinerosPlace().getStaticPlaceInformation().getSubNet().equals(subnet)) {
-                serverPlaces.add(p);
-            }
-        }
-
-        for (RefPlace rp : petriNet.allRefPlaces()) {
-            if (rp.getSubNet().equals(subnet)) {
-                serverRefPlaces.add(rp);
-            }
-        }
-
-        for (RefTransition rt : petriNet.allRefTransitions()) {
-            if (rt.getSubNet().equals(subnet)) {
-                serverRefTransitions.add(rt);
-            }
-        }
-    }
-
-    private static Set<PnObject> getObjectsBySubnet(PetriNet petriNet, String subnet) {
-
-        Set<PnObject> pnObjects = new HashSet<>();
-
-        for (Transition t : petriNet.allTransitions()) {
-            if (t.asDinerosTransition().getStaticTransitionInformation().getSubNet().equals(subnet)) {
-                pnObjects.add(t);
-            }
-        }
-
-        for (Place p : petriNet.allPlaces()) {
-            if (p.asDinerosPlace().getStaticPlaceInformation().getSubNet().equals(subnet)) {
-                pnObjects.add(p);
-            }
-        }
-
-        for (RefPlace rp : petriNet.allRefPlaces()) {
-            if (rp.getSubNet().equals(subnet)) {
-                pnObjects.add(rp);
-            }
-        }
-
-        for (RefTransition rt : petriNet.allRefTransitions()) {
-            if (rt.getSubNet().equals(subnet)) {
-                pnObjects.add(rt);
-            }
-        }
-
-        return pnObjects;
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ReferenceFlatter.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ReferenceFlatter.java
index 8dd23eff2cbe4bed55a9615d81ae373eaddda8f3..4539aadebf850e725b2590e8936d9fcbfc3a5527 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ReferenceFlatter.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ReferenceFlatter.java
@@ -5,7 +5,7 @@ import de.tudresden.inf.st.pnml.jastadd.model.*;
 import java.util.HashSet;
 import java.util.Set;
 
-public class ReferenceFlatter extends Flatter{
+public class ReferenceFlatter {
 
     private static void findPlaceReferences(PlaceNode placeNode, Set<PlaceNode> nodes){
 
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/SignalFlatter.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/SignalFlatter.java
deleted file mode 100644
index a6345ae7310bf55aceb09ee04b80f3efb7916eb0..0000000000000000000000000000000000000000
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/SignalFlatter.java
+++ /dev/null
@@ -1,249 +0,0 @@
-package de.tudresden.inf.st.pnml.flatter.transform;
-
-import de.tudresden.inf.st.pnml.flatter.template.PrimitiveTemplates;
-import de.tudresden.inf.st.pnml.flatter.template.SignalTemplates;
-import de.tudresden.inf.st.pnml.flatter.template.TemplateConstants;
-import de.tudresden.inf.st.pnml.jastadd.model.*;
-
-import java.util.*;
-
-public class SignalFlatter extends Flatter{
-
-    /*public static PetriNet flatSignals(PetriNet petriNet) {
-
-        Page topPage = petriNet.getPage(0);
-
-        Map<String, List<InputSignalTransition>> signalMap = new HashMap<>();
-        Map<String, OutputSignalPlace> orPlacePairs = new HashMap<>();
-
-        // construct signal-id to transition mapping
-        for (Transition t : petriNet.allTransitions()) {
-
-            if (t.asInputSignalTransition().getStaticInputSignalBindingList() != null) {
-                for (InputSignalBinding isb : t.asInputSignalTransition().getStaticInputSignalBindingList()) {
-
-                    if (signalMap.containsKey(isb.getInputSignalID())) {
-                        signalMap.get(isb.getInputSignalID()).add(t.asInputSignalTransition());
-                    } else {
-                        List<InputSignalTransition> transitionList = new ArrayList<>();
-                        transitionList.add(t.asInputSignalTransition());
-                        signalMap.put(isb.getInputSignalID(), transitionList);
-                    }
-                }
-            }
-        }
-
-        // build clauses
-        int signalCount = 0;
-        for (Map.Entry<String, List<InputSignalTransition>> entry : signalMap.entrySet()) {
-
-            // build signal root net
-            PetriNet signalTemplate = SignalTemplates.getInputSignalTemplate(entry.getKey() + "-base");
-            includeTemplateInstance(petriNet, signalTemplate, "signals", "signals");
-
-            String targetId = TemplateConstants.INPUT_SIGNAL_PLACE_ACTIVE + "-" + entry.getKey() + "-base";
-            String targetId2 = TemplateConstants.INPUT_SIGNAL_PLACE_INACTIVE + "-" + entry.getKey() + "-base";
-            Place coreInPlace = getPlaceByID(petriNet, targetId);
-
-            for (InputSignalBinding isb : entry.getValue().get(0).getStaticInputSignalBindingList()) {
-                if (isb.getInputSignalID().equals(entry.getKey())) {
-
-                    if (isb.getInputSignalValue() == 1) {
-                        getPlaceByID(petriNet, targetId).getInitialMarking().setText(1);
-                    } else {
-                        getPlaceByID(petriNet, targetId2).getInitialMarking().setText(1);
-                    }
-                }
-            }
-
-            int andCount = 0;
-            int orCount = 0;
-
-            for (int i = 0; i < entry.getValue().size(); i++) {
-                String actToInActId = TemplateConstants.INPUT_SIGNAL_TRANSITION_TO_INACTIVE + "-" + entry.getKey() + "-base";
-                String inActToActId = TemplateConstants.INPUT_SIGNAL_TRANSITION_TO_ACTIVE + "-" + entry.getKey() + "-base";
-
-                boolean isActiveSignal = false;
-                for (InputSignalBinding isb : entry.getValue().get(i).getStaticInputSignalBindingList()) {
-                    if (isb.getInputSignalID().equals(entry.getKey())) {
-                        isActiveSignal = isb.getInputSignalValue() == 1;
-                        break;
-                    }
-                }
-
-                // build AND-based clauses
-                if (!entry.getValue().get(i).getInputSignalClause().printExp().contains("OR")) {
-
-                    if (andCount == 0) {
-                        createAndIncludeArc(topPage, "IoTransitionToSignal-" + entry.getKey() + "-base", entry.getValue().get(i), coreInPlace);
-                        createAndIncludeArc(topPage, "IoTransitionFromSignal-" + entry.getKey() + "-base", coreInPlace, entry.getValue().get(i));
-                        petriNet.flushTreeCache();
-                    } else {
-                        attachANDSignalNetToBaseSignalNet(petriNet, entry.getValue().get(i),
-                                Objects.requireNonNull(getTransitionByID(petriNet, actToInActId)).asInputSignalTransition(),
-                                getTransitionByID(petriNet, inActToActId).asInputSignalTransition(), i, entry.getKey(), isActiveSignal);
-                    }
-
-                    andCount++;
-                }
-
-                // build OR-based clauses
-                if (entry.getValue().get(i).getInputSignalClause().printExp().contains("OR")) {
-                    // has already connected or signal connecting place?
-                    OutputSignalPlace orTruePlace = null;
-                    OutputSignalPlace orFalsePlace = null;
-
-                    for (Place p : entry.getValue().get(i).incomingPlaces()) {
-                        if (p.getId().contains(TemplateConstants.INPUT_SIGNAL_PLACE_OR_CONNECTION_TRUE_PREFIX)) {
-                            orTruePlace = p.asOutputSignalPlace();
-                            orFalsePlace = orPlacePairs.get(orTruePlace.getId());
-                            break;
-                        }
-                    }
-
-                    if (orTruePlace == null) {
-                        Pair<OutputSignalPlace, OutputSignalPlace> res =
-                                buildOrBaseNetElements(petriNet, topPage, signalCount, i, entry.getValue().get(i), orPlacePairs);
-                        orTruePlace = res._1;
-                        orFalsePlace = res._2;
-                    }
-
-                    if (andCount == 0 && orCount == 0) {
-                        attachORSignalNetToBaseSignalNet(petriNet, getTransitionByID(petriNet, actToInActId).asInputSignalTransition(),
-                                getTransitionByID(petriNet, inActToActId).asInputSignalTransition(), orTruePlace,
-                                orFalsePlace, i, entry.getKey(), true, isActiveSignal);
-                        System.out.println("BASE");
-
-                    } else {
-                        attachORSignalNetToBaseSignalNet(petriNet, getTransitionByID(petriNet, actToInActId).asInputSignalTransition(),
-                                getTransitionByID(petriNet, inActToActId).asInputSignalTransition(), orTruePlace,
-                                orFalsePlace, i, entry.getKey(), false, isActiveSignal);
-                        System.out.println("EXTEND");
-                    }
-                    orCount++;
-                }
-            }
-
-            signalCount++;
-        }
-
-        // include negations
-        // TODO
-
-        return petriNet;
-    }
-
-    private static Pair<OutputSignalPlace, OutputSignalPlace> buildOrBaseNetElements(
-            PetriNet petriNet, Page topPage, int signalCount, int i, Transition transition, Map<String, OutputSignalPlace> orPlacePairs) {
-
-        OutputSignalPlace orPlaceFalse = PrimitiveTemplates.getOutputSignalPlace();
-        assert orPlaceFalse != null;
-        orPlaceFalse.setId(TemplateConstants.INPUT_SIGNAL_PLACE_OR_CONNECTION_FALSE_PREFIX + "-" + signalCount + "-" + i);
-        Name fName = new Name();
-        fName.setText(TemplateConstants.INPUT_SIGNAL_PLACE_OR_CONNECTION_FALSE_PREFIX + "-" + signalCount + "-" + i);
-        orPlaceFalse.setName(fName);
-        PlaceInformation fPi = new PlaceInformation();
-        fPi.setLocation("signals");
-        fPi.setSubNet("signals");
-        orPlaceFalse.setMutualPlaceInformation(fPi);
-
-        OutputSignalPlace orPlaceTrue = PrimitiveTemplates.getOutputSignalPlace();
-        orPlaceTrue.setId(TemplateConstants.INPUT_SIGNAL_PLACE_OR_CONNECTION_TRUE_PREFIX + "-" + signalCount + "-" + i);
-        Name tName = new Name();
-        tName.setText(TemplateConstants.INPUT_SIGNAL_PLACE_OR_CONNECTION_TRUE_PREFIX + "-" + signalCount + "-" + i);
-        orPlaceTrue.setName(tName);
-        PlaceInformation tPi = new PlaceInformation();
-        tPi.setLocation("signals");
-        tPi.setSubNet("signals");
-        orPlaceTrue.setMutualPlaceInformation(tPi);
-
-        topPage.addObject(orPlaceTrue);
-        topPage.addObject(orPlaceFalse);
-
-        createAndIncludeArc(topPage, orPlaceTrue.getId() + "-to-" + transition.getId(), orPlaceTrue, transition);
-        createAndIncludeArc(topPage, transition.getId() + "-to-" + orPlaceTrue.getId(), transition, orPlaceTrue);
-
-        petriNet.flushTreeCache();
-
-        orPlacePairs.put(orPlaceTrue.getId(), orPlaceFalse);
-        return new Pair<>(orPlaceTrue, orPlaceFalse);
-    }
-
-    private static void attachORSignalNetToBaseSignalNet(PetriNet petriNet, InputSignalTransition inactiveT,
-                                                         InputSignalTransition activeT, OutputSignalPlace orTruePlace, OutputSignalPlace orFalsePlace,
-                                                         int count, String signalId, boolean isBase, boolean isActive) {
-
-        Page topPage = petriNet.getPage(0);
-        OutputSignalPlace aOsp = Objects.requireNonNull(getPlaceByID(petriNet, TemplateConstants.INPUT_SIGNAL_PLACE_ACTIVE + "-" + signalId + "-base")).asOutputSignalPlace();
-        OutputSignalPlace iOsp = Objects.requireNonNull(getPlaceByID(petriNet, TemplateConstants.INPUT_SIGNAL_PLACE_INACTIVE + "-" + signalId + "-base")).asOutputSignalPlace();
-
-        if (!isBase) {
-            aOsp = Objects.requireNonNull(getPlaceByID(petriNet, TemplateConstants.INPUT_SIGNAL_PLACE_ACTIVE + "-" + signalId + "-base")).asOutputSignalPlace().treeCopy();
-            iOsp = Objects.requireNonNull(getPlaceByID(petriNet, TemplateConstants.INPUT_SIGNAL_PLACE_INACTIVE + "-" + signalId + "-base")).asOutputSignalPlace().treeCopy();
-            renameSignalPlace(count, signalId, aOsp, iOsp);
-
-            topPage.addObject(aOsp);
-            topPage.addObject(iOsp);
-            petriNet.flushTreeCache();
-        }
-
-        // marking
-        if (isActive) {
-            aOsp.getInitialMarking().setText(1);
-            int orTruePlaceMarking = orTruePlace.getInitialMarking().getText();
-            orTruePlace.getInitialMarking().setText(orTruePlaceMarking + 1);
-        } else {
-            iOsp.getInitialMarking().setText(1);
-            int orFalsePlaceMarking = orFalsePlace.getInitialMarking().getText();
-            orFalsePlace.getInitialMarking().setText(orFalsePlaceMarking + 1);
-        }
-
-        createAndIncludeArc(topPage, TemplateConstants.ARC_T_ACTIVE_TO_TRUE + "-" + signalId + "-" + count, activeT, orTruePlace);
-        createAndIncludeArc(topPage, TemplateConstants.ARC_FALSE_TO_T_ACTIVE + "-" + signalId + "-" + count, orFalsePlace, activeT);
-        createAndIncludeArc(topPage, TemplateConstants.ARC_T_INACTIVE_TO_FALSE + "-" + signalId + "-" + count, inactiveT, orFalsePlace);
-        createAndIncludeArc(topPage, TemplateConstants.ARC_TRUE_TO_T_INACTIVE + "-" + signalId + "-" + count, orTruePlace, inactiveT);
-
-        if (!isBase) {
-            createAndIncludeArc(topPage, "arc-or-1-" + signalId + "-" + count, aOsp, inactiveT);
-            createAndIncludeArc(topPage, "arc-or-2-" + signalId + "-" + count, inactiveT, iOsp);
-            createAndIncludeArc(topPage, "arc-or-3-" + signalId + "-" + count, iOsp, activeT);
-            createAndIncludeArc(topPage, "arc-or-4-" + signalId + "-" + count, activeT, aOsp);
-        }
-    }
-
-    private static void attachANDSignalNetToBaseSignalNet(PetriNet petriNet, InputSignalTransition transition, InputSignalTransition inactiveT, InputSignalTransition activeT, int count, String signalId, boolean isActive) {
-
-        Page topPage = petriNet.getPage(0);
-
-        OutputSignalPlace aOsp = Objects.requireNonNull(getPlaceByID(petriNet, TemplateConstants.INPUT_SIGNAL_PLACE_ACTIVE + "-" + signalId + "-base")).asOutputSignalPlace().treeCopy();
-        OutputSignalPlace iOsp = Objects.requireNonNull(getPlaceByID(petriNet, TemplateConstants.INPUT_SIGNAL_PLACE_INACTIVE + "-" + signalId + "-base")).asOutputSignalPlace().treeCopy();
-        renameSignalPlace(count, signalId, aOsp, iOsp);
-
-        createAndIncludeArc(topPage, "arc-and-1-" + signalId + "-" + count, aOsp, inactiveT);
-        createAndIncludeArc(topPage, "arc-and-2-" + signalId + "-" + count, inactiveT, iOsp);
-        createAndIncludeArc(topPage, "arc-and-3-" + signalId + "-" + count, iOsp, activeT);
-        createAndIncludeArc(topPage, "arc-and-4-" + signalId + "-" + count, activeT, aOsp);
-
-        createAndIncludeArc(topPage, "IoTransitionToSignal-" + signalId + "-" + count, transition, aOsp);
-        createAndIncludeArc(topPage, "IoTransitionFromSignal-" + signalId + "-" + count, aOsp, transition);
-
-        topPage.addObject(aOsp);
-        topPage.addObject(iOsp);
-
-        // marking
-        if (isActive) {
-            aOsp.getInitialMarking().setText(1);
-        } else {
-            iOsp.getInitialMarking().setText(1);
-        }
-
-        petriNet.flushTreeCache();
-    }
-
-    private static void renameSignalPlace(int count, String signalId, OutputSignalPlace aOsp, OutputSignalPlace iOsp) {
-        aOsp.setId(TemplateConstants.INPUT_SIGNAL_PLACE_ACTIVE + "-" + signalId + "-" + count );
-        iOsp.setId(TemplateConstants.INPUT_SIGNAL_PLACE_INACTIVE + "-" + signalId + "-" + count);
-        aOsp.getName().setText(TemplateConstants.INPUT_SIGNAL_PLACE_ACTIVE + "-" + signalId + "-" + count);
-        iOsp.getName().setText(TemplateConstants.INPUT_SIGNAL_PLACE_INACTIVE + "-" + signalId + "-" + count);
-    }*/
-}
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ToolspecificsTransformer.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ToolspecificsTransformer.java
index 1009f280cde7c40bc1c99be423b9547d51ed2924..a1443abc5e25cd06231f1e5513c874d2fa4bdce0 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ToolspecificsTransformer.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ToolspecificsTransformer.java
@@ -14,7 +14,7 @@ public class ToolspecificsTransformer {
      * serverInput/serverOutput remain unchanged because we know the new one are id + index + suffix
      * only client-wise channels are updated
      */
-    public static void updateServiceTransitionToolspecifics(PetriNet petriNet, int serviceCapacity, Page sPage) {
+    public static void updateTransitionToolspecifics(PetriNet petriNet, int serviceCapacity, Page sPage) {
 
         Set<String> pagePlaceIds = new HashSet<>();
 
@@ -42,7 +42,7 @@ public class ToolspecificsTransformer {
                             newSc.setId(UUID.randomUUID().toString());
                             newSc.setRequestPlaceId(sc.getRequestPlaceId() + "-" + i + "-" + PnmlConstants.PAGE_SERVER_INSTANCE_SUFFIX);
                             newSc.setResponsePlaceId(sc.getResponsePlaceId() + "-" + i + "-" + PnmlConstants.PAGE_SERVER_INSTANCE_SUFFIX);
-                            dt.getMutableTransitionInformation().asServiceTransitionInformation().getClientChannelList().add(newSc);
+                            dt.getMutableTransitionInformation().asServiceTransitionInformation().addClientChannel(newSc);
                         }
 
                         sc.removeSelf();
@@ -50,6 +50,30 @@ public class ToolspecificsTransformer {
                     }
                 }
             }
+
+            if (dt.getStaticTransitionInformation().isTopicTransitionInformation()) {
+
+                if (dt.getMutableTransitionInformation() == null) {
+                    dt.setMutableTransitionInformation(dt.getStaticTransitionInformation().asTopicTransitionInformation().treeCopyNoTransform());
+                }
+
+                for (PublisherPort pp : dt.getMutableTransitionInformation().asTopicTransitionInformation().getPublisherPorts()) {
+
+                    if (pagePlaceIds.contains(pp.getPlaceId().split("-")[0])) {
+
+                        for (int i = 0; i < serviceCapacity; i++) {
+
+                            PublisherPort newPp = new PublisherPort();
+                            newPp.setPlaceId(pp.getPlaceId() + "-" + i + "-" + PnmlConstants.PAGE_SERVER_INSTANCE_SUFFIX);
+                            newPp.setLimit(pp.getLimit());
+                            dt.getMutableTransitionInformation().asTopicTransitionInformation().addPublisherPort(newPp);
+                        }
+
+                        pp.removeSelf();
+                        break;
+                    }
+                }
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/Flatter.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/TransformationUtils.java
similarity index 62%
rename from src/main/java/de/tudresden/inf/st/pnml/flatter/transform/Flatter.java
rename to src/main/java/de/tudresden/inf/st/pnml/flatter/transform/TransformationUtils.java
index 1f97368f2006c3569af01104a8bd5de72b95b5fa..fba99bc5405ece9e7cd803fdb73cc9c679fa6feb 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/Flatter.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/TransformationUtils.java
@@ -2,9 +2,11 @@ package de.tudresden.inf.st.pnml.flatter.transform;
 
 import de.tudresden.inf.st.pnml.jastadd.model.*;
 
-public abstract class Flatter {
+import java.util.Map;
 
-    protected static Arc createArc(String id, Node s, Node t) {
+public class TransformationUtils {
+
+    public static Arc createArc(String id, Node s, Node t) {
 
         Arc a = new Arc();
         a.setId(id);
@@ -13,14 +15,14 @@ public abstract class Flatter {
         return a;
     }
 
-    protected static Arc createAndIncludeArc(Page page, String id, Node s, Node t) {
+    public static Arc createAndIncludeArc(Page page, String id, Node s, Node t) {
 
         Arc a = createArc(id, s, t);
         page.addObject(a);
         return a;
     }
 
-    protected static Arc createAndIncludeInhibitorArc(Page page, String id, Node s, Node t) {
+    public static Arc createAndIncludeInhibitorArc(Page page, String id, Node s, Node t) {
 
         Arc a = createArc(id, s, t);
         ToolInfo ti = new ToolInfo();
@@ -35,32 +37,42 @@ public abstract class Flatter {
         return a;
     }
 
-   /* protected static void includeTemplateInstance(PetriNet petriNet, PetriNet templateInstance, String subnet, String location) {
+    public static void includeTemplateInstance(Page page, PetriNet petriNet, PetriNet templateInstance, String subnet, String node, Map<String, Node> refs) {
 
-        // after tina-flat we do only have on page
-        Page topPage = petriNet.getPage(0);
+        for(RefTransition rt : templateInstance.allRefTransitions()){
+            if(refs.containsKey(rt.getId())){
+                rt.setRef(refs.get(rt.getId()).asTransitionNode());
+            }
+            page.addObject(rt);
+
+        }
+
+        for(RefPlace rp : templateInstance.allRefPlaces()){
+            if(refs.containsKey(rp.getId())){
+                rp.setRef(refs.get(rp.getId()).asPlaceNode());
+            }
+            page.addObject(rp);
+        }
 
         // include places, transitions
         for (Transition t : templateInstance.allTransitions()) {
 
-            TransitionInformation newTi = new DefaultTransitionInformation();
-            newTi.setLocation(location);
+            SignalTransitionInformation newTi = new SignalTransitionInformation();
+            newTi.setNode(node);
             newTi.setSubNet(subnet);
-            newTi.setType(t.asInputSignalTransition().getStaticTransitionInformation().getType());
-            t.asInputSignalTransition().setMutualTransitionInformation(newTi);
+            t.asDinerosTransition().setMutableTransitionInformation(newTi);
 
-            topPage.addObject(t);
+            page.addObject(t);
         }
 
         for (Place p : templateInstance.allPlaces()) {
 
             PlaceInformation newPi = new PlaceInformation();
-            newPi.setLocation(location);
+            newPi.setNode(node);
             newPi.setSubNet(subnet);
-            newPi.setType(p.asOutputSignalPlace().getStaticPlaceInformation().getType());
-            p.asOutputSignalPlace().setMutualPlaceInformation(newPi);
+            p.asDinerosPlace().setMutablePlaceInformation(newPi);
 
-            topPage.addObject(p);
+            page.addObject(p);
         }
 
         petriNet.flushTreeCache();
@@ -69,7 +81,6 @@ public abstract class Flatter {
         for (Arc a : templateInstance.allArcs()) {
             Arc newArc = new Arc();
             newArc.setId("arc-" + a.getSource().getId() + "-" + a.getTarget().getId());
-            //     System.out.println("Target: " + a.getTarget().getId());
             newArc.setTarget((Node) getPnObjectByID(petriNet, a.getTarget().getId()));
             newArc.setSource((Node) getPnObjectByID(petriNet, a.getSource().getId()));
 
@@ -81,14 +92,13 @@ public abstract class Flatter {
                 newArc.addToolspecific(ti);
             }
 
-            topPage.addObject(newArc);
+            page.addObject(newArc);
         }
 
         petriNet.flushTreeCache();
-    }*/
-
+    }
 
-    protected static Place getPlaceByID(PetriNet petriNet, String Id) {
+    public static Place getPlaceByID(PetriNet petriNet, String Id) {
 
         for (Place p : petriNet.allPlaces()) {
             if (p.getId().equals(Id)) {
@@ -99,7 +109,7 @@ public abstract class Flatter {
         return null;
     }
 
-    protected static Transition getTransitionByID(PetriNet petriNet, String Id) {
+    public static Transition getTransitionByID(PetriNet petriNet, String Id) {
 
         for (Transition t : petriNet.allTransitions()) {
             if (t.getId().equals(Id)) {
@@ -110,7 +120,7 @@ public abstract class Flatter {
         return null;
     }
 
-    protected static PnObject getPnObjectByID(PetriNet petriNet, String Id) {
+    public static PnObject getPnObjectByID(PetriNet petriNet, String Id) {
 
         for (PnObject po : petriNet.allObjects()) {
             if (po.getId().equals(Id)) {
diff --git a/src/main/resources/templates/TopicPublisherTemplate.pnml b/src/main/resources/templates/TopicPublisherTemplate.pnml
index 1345b7c704d087b0042a0bbf88634acc4c111d57..53f7e1031123cfbc331b4b8b8ff9f0f0b0c4f338 100644
--- a/src/main/resources/templates/TopicPublisherTemplate.pnml
+++ b/src/main/resources/templates/TopicPublisherTemplate.pnml
@@ -3,6 +3,48 @@
         <name>
             <text>TopicPublisherTemplate</text>
         </name>
+
+        <!-- the reference target is just used here, because pnml does not allow dangling refs -->
+        <referencePlace id="PublisherPlaceRef" ref="PublisherCapacityPlace">
+            <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                <location>none</location>
+                <subnet>none</subnet>
+            </toolspecific>
+            <name>
+                <text>PublisherPlaceRef</text>
+                <graphics>
+                    <offset x="0" y="0" />
+                </graphics>
+            </name>
+            <graphics>
+                <position x="20" y="20"/>
+            </graphics>
+        </referencePlace>
+
+        <arc id="arc-6" source="PublisherPlaceRef" target="PublisherOverflowTransition">
+        </arc>
+        <arc id="arc-7" source="PublisherPlaceRef" target="PublisherInputTransition">
+        </arc>
+
+        <referencePlace id="PublisherChannelPlaceRef" ref="PublisherCapacityPlace">
+            <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                <location>none</location>
+                <subnet>none</subnet>
+            </toolspecific>
+            <name>
+                <text>PublisherChannelPlaceRef</text>
+                <graphics>
+                    <offset x="0" y="0" />
+                </graphics>
+            </name>
+            <graphics>
+                <position x="20" y="20"/>
+            </graphics>
+        </referencePlace>
+
+        <arc id="arc-8" source="PublisherOutputTransition" target="PublisherChannelPlaceRef">
+        </arc>
+
         <page id="PublisherTemplatePage">
             <place id="PublisherCapacityPlace">
                 <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
diff --git a/src/main/resources/templates/TopicSubCallbackQueueTemplate.pnml b/src/main/resources/templates/TopicSubCallbackQueueTemplate.pnml
index e4ee48d6d7f9dca7e746f92c017eda40be53b191..f8775f893a04e002c4a416edccf46dea4c24a226 100644
--- a/src/main/resources/templates/TopicSubCallbackQueueTemplate.pnml
+++ b/src/main/resources/templates/TopicSubCallbackQueueTemplate.pnml
@@ -4,6 +4,38 @@
             <text>TopicSubCallbackTemplate</text>
         </name>
         <page id="TopicSubCallbackTemplatePage">
+
+            <!-- the reference target is just used here, because pnml does not allow dangling refs -->
+            <referenceTransition id="CallbackInputRefTransition" ref="CallbackInputTransition">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>channel</location>
+                    <subnet>channel</subnet>
+                </toolspecific>
+            </referenceTransition>
+
+            <arc id="arc-8" source="CallbackInputRefTransition" target="CallbackConnectorPlace">
+            </arc>
+
+            <!-- the reference target is just used here, because pnml does not allow dangling refs -->
+            <referencePlace id="CallbackRefPlace" ref="CallbackInputPlace">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>none</location>
+                    <subnet>none</subnet>
+                </toolspecific>
+                <name>
+                    <text>CallbackRefPlace</text>
+                    <graphics>
+                        <offset x="0" y="0" />
+                    </graphics>
+                </name>
+                <graphics>
+                    <position x="20" y="20"/>
+                </graphics>
+            </referencePlace>
+
+            <arc id="arc-9" source="CallbackOutputTransition" target="CallbackRefPlace">
+            </arc>
+
             <place id="CallbackCapacityPlace">
                 <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
                     <location>none</location>
@@ -142,6 +174,8 @@
             </arc>
             <arc id="arc-6" source="CallbackInputPlace" target="CallbackInputTransition">
             </arc>
+            <arc id="arc-7" source="CallbackInputPlace" target="CallbackOverflowTransition">
+            </arc>
         </page>
     </net>
 </pnml>
diff --git a/src/main/resources/templates/TopicSubDispatcherTemplate.pnml b/src/main/resources/templates/TopicSubDispatcherTemplate.pnml
index e060187c9d8cf92c105d56b9b0c9a38b46a37d82..431fecefbc6365350972f81bec23f030520219ab 100644
--- a/src/main/resources/templates/TopicSubDispatcherTemplate.pnml
+++ b/src/main/resources/templates/TopicSubDispatcherTemplate.pnml
@@ -3,7 +3,17 @@
         <name>
             <text>TopicSubDispatcherTemplate</text>
         </name>
+
         <page id="TopicSubDispatcherTemplatePage">
+
+            <!-- the reference target is just used here, because pnml does not allow dangling refs -->
+            <referenceTransition id="DispatcherChannelTransitionRef" ref="DispatcherInputTransition">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>channel</location>
+                    <subnet>channel</subnet>
+                </toolspecific>
+            </referenceTransition>
+
             <place id="DispatcherCapacityPlace">
                 <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
                     <location>none</location>
@@ -144,6 +154,8 @@
             </arc>
             <arc id="arc-7" source="DispatcherInputPlace" target="DispatcherOverflowTransition">
             </arc>
+            <arc id="arc-8" source="DispatcherChannelTransitionRef" target="DispatcherInputPlace">
+            </arc>
         </page>
     </net>
 </pnml>