[ONOS-7948] Netconf driver for Lumentum ROADM-20.
Added support for flowrules coming from the compilation of an OpticalConnectivityIntent.
FlowRules coming from ROADM app are still supported.
Minor updates to DeviceDiscovery and PowerConfig.

Patch 2: Driver and OpticalPathIntent support for partner-ports.
Now bidirectional intents can be configured also in presence of unidirectional links.
ROADM app visualizes devices of type TERMINAL_DEVICE and partner port details.
Checkstyle.

Patch 3: [ONOS-7974] [ONOS-79076] partner-port renamed to reverse-port. Bug fix.
Addressed comments by Ramon Casellas and Andrea Campanella. Checkstyles.

Patch 4: documentation.

Patch 5: addressed comments by Andrea Campanella.

Patch 6: checkstyle.

Change-Id: Ie5ca41eee6cb6f8f87f076f2af19c99cadd6d851
diff --git a/apps/optical-model/src/main/java/org/onosproject/net/optical/intent/impl/compiler/OpticalPathIntentCompiler.java b/apps/optical-model/src/main/java/org/onosproject/net/optical/intent/impl/compiler/OpticalPathIntentCompiler.java
index d269843..f2a20fa 100644
--- a/apps/optical-model/src/main/java/org/onosproject/net/optical/intent/impl/compiler/OpticalPathIntentCompiler.java
+++ b/apps/optical-model/src/main/java/org/onosproject/net/optical/intent/impl/compiler/OpticalPathIntentCompiler.java
@@ -17,6 +17,12 @@
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.Port;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Deactivate;
@@ -24,11 +30,7 @@
 import org.osgi.service.component.annotations.ReferenceCardinality;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Device;
 import org.onosproject.net.Device.Type;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
 import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.device.DeviceServiceAdapter;
 import org.onosproject.net.flow.DefaultFlowRule;
@@ -204,7 +206,7 @@
      */
     private List<FlowRule> createReverseRules(OpticalPathIntent intent) {
         TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
-        selectorBuilder.matchInPort(intent.dst().port());
+        selectorBuilder.matchInPort(reversePort(intent.dst().deviceId(), intent.dst().port()));
 
         List<FlowRule> rules = new LinkedList<>();
 
@@ -219,7 +221,7 @@
             if (!isTransparent(intent.src().deviceId())) {
                 treatmentBuilder.add(Instructions.modL0Lambda(intent.lambda()));
             }
-            treatmentBuilder.setOutput(intent.src().port());
+            treatmentBuilder.setOutput(reversePort(intent.src().deviceId(), intent.src().port()));
 
             FlowRule rule = DefaultFlowRule.builder()
                     .forDevice(intent.src().deviceId())
@@ -240,7 +242,7 @@
             if (!isTransparent(current.deviceId())) {
                 treatmentBuilder.add(Instructions.modL0Lambda(intent.lambda()));
             }
-            treatmentBuilder.setOutput(link.dst().port());
+            treatmentBuilder.setOutput(reversePort(link.dst().deviceId(), link.dst().port()));
 
             FlowRule rule = DefaultFlowRule.builder()
                     .forDevice(current.deviceId())
@@ -257,7 +259,7 @@
             }
 
             current = link.src();
-            selectorBuilder.matchInPort(link.src().port());
+            selectorBuilder.matchInPort(reversePort(link.src().deviceId(), link.src().port()));
             if (!isTransparent(current.deviceId())) {
                 selectorBuilder.add(Criteria.matchLambda(intent.lambda()));
                 selectorBuilder.add(Criteria.matchOchSignalType(intent.signalType()));
@@ -266,7 +268,7 @@
 
         // Build the egress ROADM rule
         TrafficTreatment.Builder treatmentLast = DefaultTrafficTreatment.builder();
-        treatmentLast.setOutput(intent.src().port());
+        treatmentLast.setOutput(reversePort(intent.src().deviceId(), intent.src().port()));
 
         FlowRule rule = new DefaultFlowRule.Builder()
                 .forDevice(intent.src().deviceId())
@@ -285,6 +287,25 @@
     }
 
     /**
+     * Returns the PortNum of reverse port if annotation is present, otherwise return PortNum of the port itself.
+     * In the OpenROADM YANG models it is used the term "partner-port.
+     *
+     * @param portNumber the port
+     * @return the PortNum of reverse port if annotation is present, otherwise PortNum of the port itself.
+     */
+    private PortNumber reversePort(DeviceId deviceId, PortNumber portNumber) {
+        Port port = deviceService.getPort(deviceId, portNumber);
+
+        String reversePort = port.annotations().value(OpticalPathIntent.REVERSE_PORT_ANNOTATION_KEY);
+        if (reversePort != null) {
+            PortNumber reversePortNumber = PortNumber.portNumber(reversePort);
+            return reversePortNumber;
+        } else {
+            return portNumber;
+        }
+    }
+
+    /**
      * Returns true if device does not accept flow rules, false otherwise.
      *
      * @param deviceId the device
diff --git a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmDeviceViewMessageHandler.java b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmDeviceViewMessageHandler.java
index 926b576..51c8946 100644
--- a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmDeviceViewMessageHandler.java
+++ b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmDeviceViewMessageHandler.java
@@ -92,7 +92,8 @@
         protected void populateTable(TableModel tm, ObjectNode payload) {
             for (Device device : deviceService.getDevices()) {
                 Type type = device.type();
-                if (type == Type.ROADM || type == Type.OPTICAL_AMPLIFIER || type == Type.FIBER_SWITCH) {
+                if (type == Type.ROADM || type == Type.TERMINAL_DEVICE
+                        || type == Type.OPTICAL_AMPLIFIER || type == Type.FIBER_SWITCH) {
                     populateRow(tm.addRow(), device);
                 }
             }
diff --git a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmPortViewMessageHandler.java b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmPortViewMessageHandler.java
index 52a73d5..192eb2e 100644
--- a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmPortViewMessageHandler.java
+++ b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmPortViewMessageHandler.java
@@ -31,6 +31,7 @@
 import org.onosproject.net.OchSignal;
 import org.onosproject.net.Port;
 import org.onosproject.net.PortNumber;
+import org.onosproject.net.intent.OpticalPathIntent;
 import org.onosproject.net.optical.OpticalAnnotations;
 import org.onosproject.ui.RequestHandler;
 import org.onosproject.ui.UiConnection;
@@ -69,6 +70,7 @@
     private static final String ROADM_SET_OPS_MODE_RESP = "roadmSetOpsModeResponse";
 
     private static final String ID = "id";
+    private static final String REVERSE_PORT = "reversePort";
     private static final String NAME = "name";
     private static final String TYPE = "type";
     private static final String ENABLED = "enabled";
@@ -82,7 +84,7 @@
     private static final String SERVICE_STATE = "serviceState";
 
     private static final String[] COLUMN_IDS = {
-            ID, TYPE, NAME, ENABLED, MIN_FREQ, MAX_FREQ, GRID, POWER_RANGE,
+            ID, REVERSE_PORT, TYPE, NAME, ENABLED, MIN_FREQ, MAX_FREQ, GRID, POWER_RANGE,
             CURRENT_POWER, SERVICE_STATE, TARGET_POWER, HAS_TARGET_POWER
     };
 
@@ -139,6 +141,8 @@
             PortNumber portNum = port.number();
             getFrequencyLimit(deviceId, portNum);
             row.cell(ID, portNum.toLong())
+                    .cell(REVERSE_PORT, RoadmUtil.getAnnotation(port.annotations(),
+                            OpticalPathIntent.REVERSE_PORT_ANNOTATION_KEY))
                     .cell(TYPE, port.type())
                     .cell(ENABLED, port.isEnabled())
                     .cell(NAME, RoadmUtil.getAnnotation(port.annotations(), AnnotationKeys.PORT_NAME))
diff --git a/apps/roadm/src/main/resources/app/view/roadmPort/roadmPort.html b/apps/roadm/src/main/resources/app/view/roadmPort/roadmPort.html
index f896ebd..57cc441 100644
--- a/apps/roadm/src/main/resources/app/view/roadmPort/roadmPort.html
+++ b/apps/roadm/src/main/resources/app/view/roadmPort/roadmPort.html
@@ -31,6 +31,7 @@
             <table>
                 <tr>
                     <td colId="id" sortable>Port Number </td>
+                    <td colId="reversePort" sortable>Reverse </td>
                     <td colId="name" sortable>Name </td>
                     <td colId="type" sortable>Type </td>
                     <td colId="enabled" sortable>Enabled </td>
@@ -56,6 +57,7 @@
                 <tr ng-repeat="item in tableData track by $index"
                     ng-class="{selected: item.id === selId}">
                     <td>{{item.id}}</td>
+                    <td>{{item.reversePort}}</td>
                     <td>{{item.name}}</td>
                     <td>{{item.type}}</td>
                     <td>{{item.enabled}}</td>