Better error handling in pseudowire implementation.

I refactored the pw handler to return meaningful very specific
errors for failures. As a result, I modified also the cli and rest
api implementations to use these fine grain errors accordingly.

Change-Id: I2429532f747c4560378c40be325b039ca0f5c925
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java
index fba6ff9..755cb68 100644
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java
+++ b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/PseudowireCodec.java
@@ -15,7 +15,9 @@
  */
 package org.onosproject.segmentrouting.web;
 
+import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import javafx.util.Pair;
 import org.onlab.packet.MplsLabel;
 import org.onlab.packet.VlanId;
 import org.onosproject.codec.CodecContext;
@@ -28,6 +30,8 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.List;
+
 import static org.onosproject.segmentrouting.pwaas.PwaasUtil.*;
 
 /**
@@ -47,6 +51,11 @@
     private static final String SERVICE_DELIM_TAG = "serviceTag";
     private static final String PW_LABEL = "pwLabel";
 
+    // JSON field names for error in return
+    private static final String FAILED_PWS = "failedPws";
+    private static final String FAILED_PW = "pw";
+    private static final String REASON = "reason";
+
     private static Logger log = LoggerFactory
             .getLogger(PseudowireCodec.class);
 
@@ -73,6 +82,44 @@
     }
 
     /**
+     * Encoded in an Object Node the pseudowire and the specificError it failed.
+     *
+     * @param failedPW The failed pseudowire
+     * @param specificError The specificError it failed
+     * @param context Our context
+     * @return A node containing the information we provided
+     */
+    public ObjectNode encodeError(DefaultL2TunnelDescription failedPW, String specificError,
+                                          CodecContext context) {
+        ObjectNode result = context.mapper().createObjectNode();
+
+        ObjectNode pw = encode(failedPW, context);
+        result.set(FAILED_PW, pw);
+        result.put(REASON, specificError);
+
+        return result;
+    }
+
+    /**
+     * Returns a JSON containing the failed pseudowires and the reason that its one failed.
+     *
+     * @param failedPws Pairs of pws and reasons.
+     * @param context The context
+     * @return ObjectNode representing the json to return
+     */
+    public ObjectNode encodeFailedPseudowires(
+            List<Pair<DefaultL2TunnelDescription, String>> failedPws,
+            CodecContext context) {
+
+        ArrayNode failedNodes = context.mapper().createArrayNode();
+        failedPws.stream()
+                .forEach(failed -> failedNodes.add(encodeError(failed.getKey(), failed.getValue(), context)));
+        final ObjectNode toReturn = context.mapper().createObjectNode();
+        toReturn.set(FAILED_PWS, failedNodes);
+        return toReturn;
+    }
+
+    /**
      * Decodes a json containg a single field with the pseudowire id.
      *
      * @param json Json to decode.