Restructured to separate stores and managers into different bundles. Reactive forwarding does not seem to work; will investigate.
diff --git a/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleManager.java b/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleManager.java
deleted file mode 100644
index 7003271..0000000
--- a/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleManager.java
+++ /dev/null
@@ -1,167 +0,0 @@
-package org.onlab.onos.net.trivial.flow.impl;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.Service;
-import org.onlab.onos.event.AbstractListenerRegistry;
-import org.onlab.onos.event.EventDeliveryService;
-import org.onlab.onos.net.Device;
-import org.onlab.onos.net.DeviceId;
-import org.onlab.onos.net.device.DeviceService;
-import org.onlab.onos.net.flow.FlowRule;
-import org.onlab.onos.net.flow.FlowRuleEvent;
-import org.onlab.onos.net.flow.FlowRuleListener;
-import org.onlab.onos.net.flow.FlowRuleProvider;
-import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
-import org.onlab.onos.net.flow.FlowRuleProviderService;
-import org.onlab.onos.net.flow.FlowRuleService;
-import org.onlab.onos.net.provider.AbstractProviderRegistry;
-import org.onlab.onos.net.provider.AbstractProviderService;
-import org.slf4j.Logger;
-
-@Component(immediate = true)
-@Service
-public class SimpleFlowRuleManager
-extends AbstractProviderRegistry<FlowRuleProvider, FlowRuleProviderService>
-implements FlowRuleService, FlowRuleProviderRegistry {
-
-    public static final String FLOW_RULE_NULL = "FlowRule cannot be null";
-    private final Logger log = getLogger(getClass());
-
-    private final AbstractListenerRegistry<FlowRuleEvent, FlowRuleListener>
-    listenerRegistry = new AbstractListenerRegistry<>();
-
-    private final SimpleFlowRuleStore store = new SimpleFlowRuleStore();
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected EventDeliveryService eventDispatcher;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected DeviceService deviceService;
-
-    @Activate
-    public void activate() {
-        eventDispatcher.addSink(FlowRuleEvent.class, listenerRegistry);
-        log.info("Started");
-    }
-
-    @Deactivate
-    public void deactivate() {
-        eventDispatcher.removeSink(FlowRuleEvent.class);
-        log.info("Stopped");
-    }
-
-    @Override
-    public Iterable<FlowRule> getFlowEntries(DeviceId deviceId) {
-        return store.getFlowEntries(deviceId);
-    }
-
-    @Override
-    public List<FlowRule> applyFlowRules(FlowRule... flowRules) {
-        List<FlowRule> entries = new ArrayList<FlowRule>();
-
-        for (int i = 0; i < flowRules.length; i++) {
-            FlowRule f = flowRules[i];
-            final Device device = deviceService.getDevice(f.deviceId());
-            final FlowRuleProvider frp = getProvider(device.providerId());
-            entries.add(store.storeFlowRule(f));
-            frp.applyFlowRule(f);
-        }
-
-        return entries;
-    }
-
-    @Override
-    public void removeFlowRules(FlowRule... flowRules) {
-        for (int i = 0; i < flowRules.length; i++) {
-            FlowRule f = flowRules[i];
-            final Device device = deviceService.getDevice(f.deviceId());
-            final FlowRuleProvider frp = getProvider(device.providerId());
-            store.removeFlowRule(f);
-            frp.removeFlowRule(f);
-        }
-
-    }
-
-    @Override
-    public void addListener(FlowRuleListener listener) {
-        listenerRegistry.addListener(listener);
-    }
-
-    @Override
-    public void removeListener(FlowRuleListener listener) {
-        listenerRegistry.removeListener(listener);
-    }
-
-    @Override
-    protected FlowRuleProviderService createProviderService(
-            FlowRuleProvider provider) {
-        return new InternalFlowRuleProviderService(provider);
-    }
-
-    private class InternalFlowRuleProviderService
-    extends AbstractProviderService<FlowRuleProvider>
-    implements FlowRuleProviderService {
-
-        protected InternalFlowRuleProviderService(FlowRuleProvider provider) {
-            super(provider);
-        }
-
-        @Override
-        public void flowRemoved(FlowRule flowRule) {
-            checkNotNull(flowRule, FLOW_RULE_NULL);
-            checkValidity();
-            FlowRuleEvent event = store.removeFlowRule(flowRule);
-
-            if (event != null) {
-                log.debug("Flow {} removed", flowRule);
-                post(event);
-            }
-        }
-
-        @Override
-        public void flowMissing(FlowRule flowRule) {
-            checkNotNull(flowRule, FLOW_RULE_NULL);
-            checkValidity();
-            // TODO Auto-generated method stub
-
-        }
-
-        @Override
-        public void flowAdded(FlowRule flowRule) {
-            checkNotNull(flowRule, FLOW_RULE_NULL);
-            checkValidity();
-
-            FlowRuleEvent event = store.addOrUpdateFlowRule(flowRule);
-            if (event == null) {
-                log.debug("Flow {} updated", flowRule);
-            } else {
-                log.debug("Flow {} added", flowRule);
-                post(event);
-            }
-        }
-
-        // Posts the specified event to the local event dispatcher.
-        private void post(FlowRuleEvent event) {
-            if (event != null) {
-                eventDispatcher.post(event);
-            }
-        }
-
-        @Override
-        public void pushFlowMetrics(Iterable<FlowRule> flowEntries) {
-            // TODO Auto-generated method stub
-
-        }
-    }
-
-}
diff --git a/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleStore.java b/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleStore.java
index dd8dce8..8ea00e7 100644
--- a/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleStore.java
+++ b/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/SimpleFlowRuleStore.java
@@ -1,55 +1,41 @@
 package org.onlab.onos.net.trivial.flow.impl;
 
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
 import org.onlab.onos.net.DeviceId;
 import org.onlab.onos.net.flow.DefaultFlowRule;
 import org.onlab.onos.net.flow.FlowRule;
 import org.onlab.onos.net.flow.FlowRuleEvent;
+import org.onlab.onos.net.flow.FlowRuleStore;
 
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multimap;
-
-import static org.onlab.onos.net.flow.FlowRuleEvent.Type.*;
+import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED;
+import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
 
 /**
  * Manages inventory of flow rules using trivial in-memory implementation.
  */
-public class SimpleFlowRuleStore {
+public class SimpleFlowRuleStore implements FlowRuleStore {
 
     // store entries as a pile of rules, no info about device tables
     private final Multimap<DeviceId, FlowRule> flowEntries = HashMultimap.create();
 
-    /**
-     * Returns the flow entries associated with a device.
-     *
-     * @param deviceId the device ID
-     * @return the flow entries
-     */
-    Iterable<FlowRule> getFlowEntries(DeviceId deviceId) {
+    @Override
+    public Iterable<FlowRule> getFlowEntries(DeviceId deviceId) {
         return ImmutableSet.copyOf(flowEntries.get(deviceId));
     }
 
-    /**
-     * Stores a new flow rule, and generates a FlowRule for it.
-     *
-     * @param rule the flow rule to add
-     * @return a flow entry
-     */
-    FlowRule storeFlowRule(FlowRule rule) {
+    @Override
+    public FlowRule storeFlowRule(FlowRule rule) {
         DeviceId did = rule.deviceId();
         FlowRule entry = new DefaultFlowRule(did,
-                rule.selector(), rule.treatment(), rule.priority());
+                                             rule.selector(), rule.treatment(), rule.priority());
         flowEntries.put(did, entry);
         return entry;
     }
 
-    /**
-     * Stores a new flow rule, or updates an existing entry.
-     *
-     * @param rule the flow rule to add or update
-     * @return flow_added event, or null if just an update
-     */
-    FlowRuleEvent addOrUpdateFlowRule(FlowRule rule) {
+    @Override
+    public FlowRuleEvent addOrUpdateFlowRule(FlowRule rule) {
         DeviceId did = rule.deviceId();
 
         // check if this new rule is an update to an existing entry
@@ -63,13 +49,8 @@
         return new FlowRuleEvent(RULE_ADDED, rule);
     }
 
-    /**
-     *
-     * @param rule the flow rule to remove
-     * @return flow_removed event, or null if nothing removed
-     */
-    FlowRuleEvent removeFlowRule(FlowRule rule) {
-
+    @Override
+    public FlowRuleEvent removeFlowRule(FlowRule rule) {
         synchronized (this) {
             if (flowEntries.remove(rule.deviceId(), rule)) {
                 return new FlowRuleEvent(RULE_REMOVED, rule);
diff --git a/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/package-info.java b/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/package-info.java
deleted file mode 100644
index 061c2a8..0000000
--- a/core/trivial/src/main/java/org/onlab/onos/net/trivial/flow/impl/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Core subsystem for tracking and manipulating global flow state.
- */
-package org.onlab.onos.net.trivial.flow.impl;