ONOS-7050 Refactored PI translation service and store

The translation store is now able to maintain mappings between
translated entities and specific instances of a PI entry in the network
(i.e. applied to a device).

The translation service has been refactored to allow users to
learn and forget translated entities.

The refactoring of the P4Runtime driver using this service will be
submitted separatelly.

Change-Id: Iaafd87d90232514853ca0dea0115dbae4f6e7886
diff --git a/core/store/dist/src/main/java/org/onosproject/store/pi/impl/AbstractDistributedPiTranslationStore.java b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/AbstractDistributedPiTranslationStore.java
new file mode 100644
index 0000000..9df6a86
--- /dev/null
+++ b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/AbstractDistributedPiTranslationStore.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.store.pi.impl;
+
+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.onosproject.net.pi.runtime.PiEntity;
+import org.onosproject.net.pi.runtime.PiHandle;
+import org.onosproject.net.pi.service.PiTranslatable;
+import org.onosproject.net.pi.service.PiTranslatedEntity;
+import org.onosproject.net.pi.service.PiTranslationEvent;
+import org.onosproject.net.pi.service.PiTranslationStore;
+import org.onosproject.net.pi.service.PiTranslationStoreDelegate;
+import org.onosproject.store.AbstractStore;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.EventuallyConsistentMapEvent;
+import org.onosproject.store.service.EventuallyConsistentMapListener;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.store.service.WallClockTimestamp;
+import org.slf4j.Logger;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.lang.String.format;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Distributed implementation of PiTranslationStore.
+ */
+@Component(immediate = true)
+public abstract class AbstractDistributedPiTranslationStore
+        <T extends PiTranslatable, E extends PiEntity>
+        extends AbstractStore<PiTranslationEvent<T, E>, PiTranslationStoreDelegate<T, E>>
+        implements PiTranslationStore<T, E> {
+
+    private static final String MAP_NAME_TEMPLATE = "onos-pi-translated-%s-map";
+
+    private final Logger log = getLogger(getClass());
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected StorageService storageService;
+
+    private EventuallyConsistentMap<PiHandle<E>, PiTranslatedEntity<T, E>>
+            translatedEntities;
+
+    private final EventuallyConsistentMapListener
+            <PiHandle<E>, PiTranslatedEntity<T, E>> entityMapListener =
+            new InternalEntityMapListener();
+
+    /**
+     * Returns a string that identifies the map maintained by this store among
+     * others that uses this abstract class.
+     *
+     * @return string
+     */
+    protected abstract String mapSimpleName();
+
+    @Activate
+    public void activate() {
+        final String fullMapName = format(MAP_NAME_TEMPLATE, mapSimpleName());
+        translatedEntities = storageService
+                .<PiHandle<E>, PiTranslatedEntity<T, E>>eventuallyConsistentMapBuilder()
+                .withName(fullMapName)
+                .withSerializer(KryoNamespaces.API)
+                .withTimestampProvider((k, v) -> new WallClockTimestamp())
+                .build();
+        translatedEntities.addListener(entityMapListener);
+        log.info("Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        translatedEntities.removeListener(entityMapListener);
+        translatedEntities = null;
+        log.info("Stopped");
+    }
+
+    @Override
+    public void addOrUpdate(PiHandle<E> handle, PiTranslatedEntity<T, E> entity) {
+        checkNotNull(handle);
+        checkNotNull(entity);
+        checkArgument(handle.entityType().equals(entity.entityType()),
+                      "Entity type must be the same for handle and translated entity");
+        translatedEntities.put(handle, entity);
+    }
+
+    @Override
+    public void remove(PiHandle<E> handle) {
+        checkNotNull(handle);
+        translatedEntities.remove(handle);
+    }
+
+    @Override
+    public PiTranslatedEntity<T, E> get(PiHandle<E> handle) {
+        checkNotNull(handle);
+        return translatedEntities.get(handle);
+    }
+
+    public Iterable<PiTranslatedEntity<T, E>> getAll() {
+        return translatedEntities.values();
+    }
+
+    private class InternalEntityMapListener
+            implements EventuallyConsistentMapListener
+                               <PiHandle<E>, PiTranslatedEntity<T, E>> {
+
+        @Override
+        public void event(EventuallyConsistentMapEvent<PiHandle<E>,
+                PiTranslatedEntity<T, E>> event) {
+            final PiTranslationEvent.Type type;
+            switch (event.type()) {
+                case PUT:
+                    type = PiTranslationEvent.Type.LEARNED;
+                    break;
+                case REMOVE:
+                    type = PiTranslationEvent.Type.FORGOT;
+                    break;
+                default:
+                    throw new IllegalArgumentException(
+                            "Unknown event type " + event.type().name());
+            }
+            notifyDelegate(new PiTranslationEvent<>(type, event.value()));
+        }
+    }
+}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiFlowRuleTranslationStore.java b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiFlowRuleTranslationStore.java
new file mode 100644
index 0000000..c123ec5
--- /dev/null
+++ b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiFlowRuleTranslationStore.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.store.pi.impl;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.pi.runtime.PiTableEntry;
+import org.onosproject.net.pi.service.PiFlowRuleTranslationStore;
+
+/**
+ * Distributed implementation of a PI translation store for flow rules.
+ */
+@Component(immediate = true)
+@Service
+public class DistributedPiFlowRuleTranslationStore
+        extends AbstractDistributedPiTranslationStore<FlowRule, PiTableEntry>
+        implements PiFlowRuleTranslationStore {
+
+    private static final String MAP_SIMPLE_NAME = "flowrule";
+
+    @Override
+    protected String mapSimpleName() {
+        return MAP_SIMPLE_NAME;
+    }
+}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiGroupTranslationStore.java b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiGroupTranslationStore.java
new file mode 100644
index 0000000..fa62ef1
--- /dev/null
+++ b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiGroupTranslationStore.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.store.pi.impl;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.pi.runtime.PiActionGroup;
+import org.onosproject.net.pi.service.PiGroupTranslationStore;
+
+/**
+ * Distributed implementation of a PI translation store for groups.
+ */
+@Component(immediate = true)
+@Service
+public class DistributedPiGroupTranslationStore
+        extends AbstractDistributedPiTranslationStore<Group, PiActionGroup>
+        implements PiGroupTranslationStore {
+
+    private static final String MAP_SIMPLE_NAME = "group";
+
+    @Override
+    protected String mapSimpleName() {
+        return MAP_SIMPLE_NAME;
+    }
+}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiTranslationStore.java b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiTranslationStore.java
deleted file mode 100644
index f19c746..0000000
--- a/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiTranslationStore.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.onosproject.store.pi.impl;
-
-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.util.KryoNamespace;
-import org.onosproject.net.pi.model.PiPipeconfId;
-import org.onosproject.net.pi.runtime.PiEntity;
-import org.onosproject.net.pi.service.PiTranslatable;
-import org.onosproject.net.pi.service.PiTranslatedEntity;
-import org.onosproject.net.pi.service.PiTranslationEvent;
-import org.onosproject.net.pi.service.PiTranslationStore;
-import org.onosproject.net.pi.service.PiTranslationStoreDelegate;
-import org.onosproject.store.AbstractStore;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.EventuallyConsistentMap;
-import org.onosproject.store.service.EventuallyConsistentMapEvent;
-import org.onosproject.store.service.EventuallyConsistentMapListener;
-import org.onosproject.store.service.StorageService;
-import org.onosproject.store.service.WallClockTimestamp;
-import org.slf4j.Logger;
-
-import java.util.Objects;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Distributed implementation of PiTranslationStore.
- */
-@Component(immediate = true)
-@Service
-public class DistributedPiTranslationStore
-        extends AbstractStore<PiTranslationEvent, PiTranslationStoreDelegate>
-        implements PiTranslationStore {
-
-    private static final String DIST_MAP_NAME = "onos-pi-translated-entities-map";
-    private final Logger log = getLogger(getClass());
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected StorageService storageService;
-
-    private EventuallyConsistentMap<PiTranslatedEntityKey, PiTranslatedEntity>
-            translatedEntities;
-
-    private final EventuallyConsistentMapListener<PiTranslatedEntityKey,
-            PiTranslatedEntity> entityMapListener = new InternalEntityMapListener();
-
-    @Activate
-    public void activate() {
-        translatedEntities = storageService
-                .<PiTranslatedEntityKey, PiTranslatedEntity>eventuallyConsistentMapBuilder()
-                .withName(DIST_MAP_NAME)
-                .withSerializer(KryoNamespace.newBuilder()
-                                        .register(KryoNamespaces.API)
-                                        .register(PiTranslatedEntityKey.class)
-                                        .build())
-                .withTimestampProvider((k, v) -> new WallClockTimestamp())
-                .build();
-        translatedEntities.addListener(entityMapListener);
-        log.info("Started");
-    }
-
-    @Deactivate
-    public void deactivate() {
-        translatedEntities.removeListener(entityMapListener);
-        translatedEntities = null;
-        log.info("Stopped");
-    }
-
-    @Override
-    public void addOrUpdate(PiTranslatable original, PiEntity translated,
-                            PiPipeconfId pipeconfId) {
-        translatedEntities.put(PiTranslatedEntityKey.of(pipeconfId, translated),
-                               new PiTranslatedEntity(original, translated, pipeconfId));
-    }
-
-    @Override
-    public void remove(PiEntity piEntity, PiPipeconfId pipeconfId) {
-        translatedEntities.remove(
-                PiTranslatedEntityKey.of(pipeconfId, piEntity));
-    }
-
-    @Override
-    public void removeAll(PiPipeconfId pipeconfId) {
-        // FIXME: this can be heavy, but we assume it won't be called that often
-        // How often we expect a pipeconf to be removed from the device/system?
-        final Set<PiTranslatedEntityKey> keysToRemove = translatedEntities
-                .keySet().parallelStream()
-                .filter(k -> k.pipeconfId.equals(pipeconfId))
-                .collect(Collectors.toSet());
-        keysToRemove.forEach(translatedEntities::remove);
-    }
-
-    @Override
-    public PiTranslatable lookup(PiEntity piEntity, PiPipeconfId pipeconfId) {
-        PiTranslatedEntity translatedEntity = translatedEntities
-                .get(PiTranslatedEntityKey.of(pipeconfId, piEntity));
-        return translatedEntity == null ? null : translatedEntity.original();
-    }
-
-
-    private class InternalEntityMapListener
-            implements EventuallyConsistentMapListener
-                               <PiTranslatedEntityKey, PiTranslatedEntity> {
-
-        @Override
-        public void event(EventuallyConsistentMapEvent<PiTranslatedEntityKey,
-                PiTranslatedEntity> event) {
-            final PiTranslationEvent.Type type;
-            switch (event.type()) {
-                case PUT:
-                    type = PiTranslationEvent.Type.LEARNED;
-                    break;
-                case REMOVE:
-                    type = PiTranslationEvent.Type.FORGOT;
-                    break;
-                default:
-                    throw new IllegalArgumentException(
-                            "Unknown event type " + event.type().name());
-            }
-            notifyDelegate(new PiTranslationEvent(type, event.value()));
-        }
-    }
-
-    /**
-     * Internal representation of a key that uniquely identifies a translated
-     * entity.
-     */
-    private static final class PiTranslatedEntityKey {
-
-        private final PiPipeconfId pipeconfId;
-        private final PiEntity piEntity;
-
-        private PiTranslatedEntityKey(PiPipeconfId pipeconfId,
-                                      PiEntity piEntity) {
-            this.pipeconfId = pipeconfId;
-            this.piEntity = piEntity;
-        }
-
-        public static PiTranslatedEntityKey of(PiPipeconfId pipeconfId,
-                                               PiEntity piEntity) {
-            return new PiTranslatedEntityKey(pipeconfId, piEntity);
-        }
-
-        public static PiTranslatedEntityKey of(PiTranslatedEntity entity) {
-            return new PiTranslatedEntityKey(entity.pipeconfId(),
-                                             entity.translated());
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(pipeconfId, piEntity);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null || getClass() != obj.getClass()) {
-                return false;
-            }
-            final PiTranslatedEntityKey other = (PiTranslatedEntityKey) obj;
-            return Objects.equals(this.pipeconfId, other.pipeconfId)
-                    && Objects.equals(this.piEntity, other.piEntity);
-        }
-    }
-}
diff --git a/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedDevicePipeconfMappingStoreTest.java b/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedDevicePipeconfMappingStoreTest.java
index 83b997d..9a31b0c 100644
--- a/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedDevicePipeconfMappingStoreTest.java
+++ b/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedDevicePipeconfMappingStoreTest.java
@@ -119,4 +119,4 @@
         store.deviceToPipeconf.clear();
     }
 
-}
\ No newline at end of file
+}
diff --git a/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedPiTranslationStoreTest.java b/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedPiTranslationStoreTest.java
new file mode 100644
index 0000000..2ba52a2
--- /dev/null
+++ b/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedPiTranslationStoreTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.store.pi.impl;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.lang3.RandomUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.pi.runtime.PiEntity;
+import org.onosproject.net.pi.runtime.PiEntityType;
+import org.onosproject.net.pi.runtime.PiHandle;
+import org.onosproject.net.pi.service.PiTranslatable;
+import org.onosproject.net.pi.service.PiTranslatedEntity;
+import org.onosproject.store.service.TestStorageService;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test for {@link AbstractDistributedPiTranslationStore}.
+ */
+public class DistributedPiTranslationStoreTest {
+
+    private AbstractDistributedPiTranslationStore<PiTranslatable, PiEntity> store;
+
+    private static final int HANDLE_HASH = RandomUtils.nextInt();
+    private static final PiTranslatable PI_TRANSLATABLE =
+            new PiTranslatable() {
+            };
+    private static final PiEntity PI_ENTITY = () -> PiEntityType.TABLE_ENTRY;
+    private static final PiHandle<PiEntity> PI_HANDLE =
+            new PiHandle<PiEntity>(DeviceId.NONE, PI_ENTITY) {
+                @Override
+                public int hashCode() {
+                    return HANDLE_HASH;
+                }
+
+                @Override
+                public boolean equals(Object other) {
+                    return other instanceof PiHandle && other.hashCode() == hashCode();
+                }
+
+                @Override
+                public String toString() {
+                    return String.valueOf(HANDLE_HASH);
+                }
+            };
+    private static final PiTranslatedEntity<PiTranslatable, PiEntity> TRANSLATED_ENTITY =
+            new PiTranslatedEntity<>(PI_TRANSLATABLE, PI_ENTITY, PI_HANDLE);
+
+    /**
+     * Sets up the store and the storage service test harness.
+     */
+    @Before
+    public void setUp() {
+        store = new AbstractDistributedPiTranslationStore<PiTranslatable, PiEntity>() {
+            @Override
+            protected String mapSimpleName() {
+                return "test";
+            }
+        };
+        store.storageService = new TestStorageService();
+        store.setDelegate(event -> {
+        });
+        store.activate();
+    }
+
+    /**
+     * Tests equality of key and value used in other tests.
+     */
+    @Test
+    public void testEquality() {
+        assertEquals(PI_HANDLE, PI_HANDLE);
+        assertEquals(TRANSLATED_ENTITY, TRANSLATED_ENTITY);
+    }
+
+    /**
+     * Test for activate.
+     */
+    @Test
+    public void activate() {
+        assertNotNull(store.storageService);
+        assertTrue("Store must have delegate",
+                   store.hasDelegate());
+        assertTrue("No value should be in the map",
+                   Lists.newArrayList(store.getAll()).isEmpty());
+    }
+
+    /**
+     * Test for deactivate.
+     */
+    @Test(expected = NullPointerException.class)
+    public void deactivate() {
+        store.deactivate();
+        store.getAll();
+    }
+
+    /**
+     * Test of value add or update.
+     */
+    @Test
+    public void addOrUpdate() {
+        store.addOrUpdate(PI_HANDLE, TRANSLATED_ENTITY);
+        assertTrue("Value should be in the map",
+                   store.get(PI_HANDLE) != null);
+        assertTrue("Exactly 1 value should be in the map",
+                   Lists.newArrayList(store.getAll()).size() == 1);
+
+        // Add again, expect 1 value.
+        store.addOrUpdate(PI_HANDLE, TRANSLATED_ENTITY);
+        assertTrue("Exactly 1 value should be in the map",
+                   Lists.newArrayList(store.getAll()).size() == 1);
+    }
+
+    /**
+     * Test of value lookup.
+     */
+    @Test
+    public void lookup() throws Exception {
+        clear();
+        addOrUpdate();
+        assertEquals("Wrong value in the map",
+                     store.get(PI_HANDLE), TRANSLATED_ENTITY);
+    }
+
+    /**
+     * Test of value removal.
+     */
+    @Test
+    public void clear() {
+        store.remove(PI_HANDLE);
+        assertTrue("Value should NOT be in the map",
+                   store.get(PI_HANDLE) == null);
+        assertTrue("No value should be in the map",
+                   Lists.newArrayList(store.getAll()).isEmpty());
+    }
+}
diff --git a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
index 9c5cb82..6a03032 100644
--- a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
+++ b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
@@ -220,6 +220,7 @@
 import org.onosproject.net.pi.model.PiTableType;
 import org.onosproject.net.pi.runtime.PiAction;
 import org.onosproject.net.pi.runtime.PiActionGroup;
+import org.onosproject.net.pi.runtime.PiActionGroupHandle;
 import org.onosproject.net.pi.runtime.PiActionGroupId;
 import org.onosproject.net.pi.runtime.PiActionGroupMember;
 import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
@@ -232,6 +233,7 @@
 import org.onosproject.net.pi.runtime.PiExactFieldMatch;
 import org.onosproject.net.pi.runtime.PiFieldMatch;
 import org.onosproject.net.pi.runtime.PiGroupKey;
+import org.onosproject.net.pi.runtime.PiHandle;
 import org.onosproject.net.pi.runtime.PiLpmFieldMatch;
 import org.onosproject.net.pi.runtime.PiMatchKey;
 import org.onosproject.net.pi.runtime.PiPacketOperation;
@@ -241,6 +243,7 @@
 import org.onosproject.net.pi.runtime.PiTableEntry;
 import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
 import org.onosproject.net.pi.runtime.PiValidFieldMatch;
+import org.onosproject.net.pi.runtime.PiTableEntryHandle;
 import org.onosproject.net.pi.service.PiTranslatable;
 import org.onosproject.net.pi.service.PiTranslatedEntity;
 import org.onosproject.net.provider.ProviderId;
@@ -634,6 +637,7 @@
                     // PI Runtime
                     PiAction.class,
                     PiActionGroup.class,
+                    PiActionGroupHandle.class,
                     PiActionGroupId.class,
                     PiActionGroupMember.class,
                     PiActionGroupMemberId.class,
@@ -646,6 +650,7 @@
                     PiExactFieldMatch.class,
                     PiFieldMatch.class,
                     PiGroupKey.class,
+                    PiHandle.class,
                     PiLpmFieldMatch.class,
                     PiMatchKey.class,
                     PiPacketOperation.class,
@@ -656,6 +661,7 @@
                     PiTernaryFieldMatch.class,
                     PiValidFieldMatch.class,
                     // PI service
+                    PiTableEntryHandle.class,
                     PiTranslatedEntity.class,
                     PiTranslatable.class,
                     // Other