[AETHER-38] Extract pipeline-dependent code from current T3 implementation

- Exposes some ofdpa specific tables and types
- Introduces a new driver behavior PipelineTraceable
- OfdpaPipelineTraceable is the first implementation of the
  new driver behavior
- New abstractions are introduced to encapsulate the input/output
  of the traceables processing
- Implements some basic unit tests for Ofdpa implementation

Change-Id: I89d3fdeda445983ec7ebfa9ebb78afb1c6d3fd8f
diff --git a/core/api/src/main/java/org/onosproject/net/PipelineTraceableOutput.java b/core/api/src/main/java/org/onosproject/net/PipelineTraceableOutput.java
new file mode 100644
index 0000000..21a9819
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/PipelineTraceableOutput.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2020-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.net;
+
+import com.google.common.collect.Lists;
+
+import java.util.List;
+
+/**
+ * Represents the output of the pipeline traceable processing.
+ */
+public final class PipelineTraceableOutput {
+
+    /**
+     * Represents the result of the pipeline traceable processing.
+     */
+    public enum PipelineTraceableResult {
+        /**
+         * Means packet went through the pipeline.
+         */
+        SUCCESS,
+        /**
+         * Means packet stopped due to missing flows.
+         */
+        NO_FLOWS,
+        /**
+         * Means packet stopped due to missing groups.
+         */
+        NO_GROUPS,
+        /**
+         * Means packet stopped due to an empty group.
+         */
+        NO_GROUP_MEMBERS,
+        /**
+         * Means packet is dropped by the pipeline.
+         */
+        DROPPED
+    }
+
+    private String log;
+    private List<PipelineTraceableHitChain> hitChains;
+    private PipelineTraceableResult result;
+
+    /**
+     * Creates a new pipeline traceable output with the specified input.
+     *
+     * @param log the trace log
+     * @param hitChains the hit chains
+     * @param result the apply result
+     */
+    private PipelineTraceableOutput(String log, List<PipelineTraceableHitChain> hitChains,
+                                    PipelineTraceableResult result) {
+        this.log = log;
+        this.hitChains = hitChains;
+        this.result = result;
+    }
+
+    /**
+     * Returns the log message as string.
+     *
+     * @return the log message
+     */
+    public String getLog() {
+        return log;
+    }
+
+    /**
+     * Returns the hit chains.
+     *
+     * @return the pipeline hit chains
+     */
+    public List<PipelineTraceableHitChain> getHitChains() {
+        return hitChains;
+    }
+
+    /**
+     * Returns the result of the computation.
+     *
+     * @return the pipeline traceable result
+     */
+    public PipelineTraceableResult getResult() {
+        return result;
+    }
+
+    /**
+     * Returns a new builder.
+     *
+     * @return an empty builder
+     */
+    public static PipelineTraceableOutput.Builder builder() {
+        return new PipelineTraceableOutput.Builder();
+    }
+
+    /**
+     * Builder of pipeline traceable entities.
+     */
+    public static final class Builder {
+
+        private StringBuilder log = new StringBuilder();
+        private List<PipelineTraceableHitChain> hitChains = Lists.newArrayList();
+        private PipelineTraceableResult result = PipelineTraceableResult.SUCCESS;
+
+        /**
+         * Appends a message to the log.
+         *
+         * @param message the log message to be appended
+         * @return this builder
+         */
+        public Builder appendToLog(String message) {
+            if (log.length() != 0) {
+                log.append("\n");
+            }
+            log.append(message);
+            return this;
+        }
+
+        private Builder setResult(PipelineTraceableResult result) {
+            // Do not override original failure
+            if (this.result == PipelineTraceableResult.SUCCESS) {
+                this.result = result;
+            }
+            return this;
+        }
+
+        /**
+         * Sets no flows in the result.
+         *
+         * @return this builder
+         */
+        public Builder noFlows() {
+            return setResult(PipelineTraceableResult.NO_FLOWS);
+        }
+
+        /**
+         * Sets no groups in the result.
+         *
+         * @return this builder
+         */
+        public Builder noGroups() {
+            return setResult(PipelineTraceableResult.NO_GROUPS);
+        }
+
+        /**
+         * Sets no flows in the result.
+         *
+         * @return this builder
+         */
+        public Builder noMembers() {
+            return setResult(PipelineTraceableResult.NO_GROUP_MEMBERS);
+        }
+
+        /**
+         * Sets dropped in the result.
+         *
+         * @return this builder
+         */
+        public Builder dropped() {
+            return setResult(PipelineTraceableResult.DROPPED);
+        }
+
+        /**
+         * Stores the provided hit chain.
+         *
+         * @param hitChain the provided hit chain
+         * @return this builder
+         */
+        public Builder addHitChain(PipelineTraceableHitChain hitChain) {
+            if (!hitChains.contains(hitChain)) {
+                hitChains.add(hitChain);
+            }
+            return this;
+        }
+
+        /**
+         * Builds a new pipeline traceable output.
+         *
+         * @return a pipeline traceable object
+         */
+        public PipelineTraceableOutput build() {
+            return new PipelineTraceableOutput(log.toString(), hitChains, result);
+        }
+
+    }
+
+}