More robust P4Runtime group handling

This patch solves the PENDING_UPDATE and PENDING_ADD_RETRY issue
observed on the ONS EU topology.

The P4Runtime action profile group handling has been re-implemented to
be robust against inconsistencies of the device mirror, which is now
periodically synchronized with the device state. Similarly, we implement
a routine in the P4RuntimeClient to cleanup unused action profile
members.

This patch includes also:
-  Refactor PI handle classes to allow creating handles without the
entity instance
- Use list instead of collections in P4RuntimeClient methods, as order
of updates sent and/or entities received from the device is important

Change-Id: I2e7964ce90f43d66680131b47ab52aca32ab55d2
diff --git a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiActionGroupMemberTest.java b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiActionGroupMemberTest.java
index 020d575..e84d48f 100644
--- a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiActionGroupMemberTest.java
+++ b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiActionGroupMemberTest.java
@@ -20,6 +20,7 @@
 import org.junit.Test;
 import org.onosproject.net.pi.model.PiActionId;
 import org.onosproject.net.pi.model.PiActionParamId;
+import org.onosproject.net.pi.model.PiActionProfileId;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
@@ -34,26 +35,37 @@
  */
 public class PiActionGroupMemberTest {
 
+    private final PiActionProfileId actionProfileId1 = PiActionProfileId.of("foo");
+    private final PiActionProfileId actionProfileId2 = PiActionProfileId.of("bar");
     private final PiActionGroupMemberId piActionGroupMemberId = PiActionGroupMemberId.of(10);
     private final PiAction piAction = PiAction.builder().withId(PiActionId.of(MOD_NW_DST))
             .withParameter(new PiActionParam(PiActionParamId.of(DST_ADDR), copyFrom(0x0a010101)))
             .build();
 
     private final PiActionGroupMember piActionGroupMember1 = PiActionGroupMember.builder()
+            .forActionProfile(actionProfileId1)
             .withId(piActionGroupMemberId)
             .withAction(piAction)
             .withWeight(10)
             .build();
     private final PiActionGroupMember sameAsPiActionGroupMember1 = PiActionGroupMember.builder()
+            .forActionProfile(actionProfileId1)
             .withId(piActionGroupMemberId)
             .withAction(piAction)
             .withWeight(10)
             .build();
     private final PiActionGroupMember piActionGroupMember2 = PiActionGroupMember.builder()
+            .forActionProfile(actionProfileId1)
             .withId(piActionGroupMemberId)
             .withAction(piAction)
             .withWeight(20)
             .build();
+    private final PiActionGroupMember piActionGroupMember1ForOtherProfile = PiActionGroupMember.builder()
+            .forActionProfile(actionProfileId2)
+            .withId(piActionGroupMemberId)
+            .withAction(piAction)
+            .withWeight(10)
+            .build();
 
     /**
      * Checks that the PiActionGroupMember class is immutable.
@@ -73,6 +85,7 @@
         new EqualsTester()
                 .addEqualityGroup(piActionGroupMember1, sameAsPiActionGroupMember1)
                 .addEqualityGroup(piActionGroupMember2)
+                .addEqualityGroup(piActionGroupMember1ForOtherProfile)
                 .testEquals();
     }