Initial sketch of codecs and REST API approach.
FIxed typos and defects.
ONOS-81

Change-Id: I789444a181abea509c354966545c927e305710d1
diff --git a/core/api/src/main/java/org/onlab/onos/codec/CodecContext.java b/core/api/src/main/java/org/onlab/onos/codec/CodecContext.java
new file mode 100644
index 0000000..6c8493e
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/codec/CodecContext.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * 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.onlab.onos.codec;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * Context for codecs to use while encoding/decoding.
+ */
+public interface CodecContext {
+
+    /**
+     * Returns the JSON object mapper.
+     *
+     * @return object mapper
+     */
+    ObjectMapper mapper();
+
+    /**
+     * Returns the JSON codec for the specified entity class.
+     *
+     * @param entityClass entity class
+     * @param <T>         entity type
+     * @return JSON codec; null if no codec available for the class
+     */
+    <T> JsonCodec<T> codec(Class<T> entityClass);
+
+    /**
+     * Returns reference to the specified service implementation.
+     *
+     * @param serviceClass service class
+     * @param <T>          service type
+     * @return JSON codec; null if no codec available for the class
+     */
+    <T> T get(Class<T> serviceClass);
+
+}
diff --git a/core/api/src/main/java/org/onlab/onos/codec/CodecService.java b/core/api/src/main/java/org/onlab/onos/codec/CodecService.java
index b8f3285..100a28c 100644
--- a/core/api/src/main/java/org/onlab/onos/codec/CodecService.java
+++ b/core/api/src/main/java/org/onlab/onos/codec/CodecService.java
@@ -33,9 +33,10 @@
      * Returns the JSON codec for the specified entity class.
      *
      * @param entityClass entity class
+     * @param <T>         entity type
      * @return JSON codec; null if no codec available for the class
      */
-    JsonCodec getCodec(Class<?> entityClass);
+    <T> JsonCodec<T> getCodec(Class<T> entityClass);
 
     /**
      * Registers the specified JSON codec for the given entity class.
@@ -43,7 +44,7 @@
      * @param entityClass entity class
      * @param codec       JSON codec
      */
-    void registerCodec(Class<?> entityClass, JsonCodec codec);
+    <T> void registerCodec(Class<T> entityClass, JsonCodec<T> codec);
 
     /**
      * Unregisters the JSON codec for the specified entity class.
diff --git a/core/api/src/main/java/org/onlab/onos/codec/JsonCodec.java b/core/api/src/main/java/org/onlab/onos/codec/JsonCodec.java
index 5dcf25c..8a8f426 100644
--- a/core/api/src/main/java/org/onlab/onos/codec/JsonCodec.java
+++ b/core/api/src/main/java/org/onlab/onos/codec/JsonCodec.java
@@ -16,7 +16,6 @@
 package org.onlab.onos.codec;
 
 import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 
@@ -31,37 +30,42 @@
     /**
      * Encodes the specified entity into JSON.
      *
-     * @param entity entity to encode
-     * @param mapper object mapper
+     * @param entity  entity to encode
+     * @param context encoding context
      * @return JSON node
      * @throws java.lang.UnsupportedOperationException if the codec does not
      *                                                 support encode operations
      */
-    public abstract ObjectNode encode(T entity, ObjectMapper mapper);
+    public ObjectNode encode(T entity, CodecContext context) {
+        throw new UnsupportedOperationException("encode() not supported");
+    }
 
     /**
      * Decodes the specified entity from JSON.
      *
-     * @param json JSON to decode
+     * @param json    JSON to decode
+     * @param context decoding context
      * @return decoded entity
      * @throws java.lang.UnsupportedOperationException if the codec does not
      *                                                 support decode operations
      */
-    public abstract T decode(ObjectNode json);
+    public T decode(ObjectNode json, CodecContext context) {
+        throw new UnsupportedOperationException("decode() not supported");
+    }
 
     /**
      * Encodes the collection of the specified entities.
      *
      * @param entities collection of entities to encode
-     * @param mapper   object mapper
+     * @param context  encoding context
      * @return JSON array
      * @throws java.lang.UnsupportedOperationException if the codec does not
      *                                                 support encode operations
      */
-    public ArrayNode encode(Iterable<T> entities, ObjectMapper mapper) {
-        ArrayNode result = mapper.createArrayNode();
+    public ArrayNode encode(Iterable<T> entities, CodecContext context) {
+        ArrayNode result = context.mapper().createArrayNode();
         for (T entity : entities) {
-            result.add(encode(entity, mapper));
+            result.add(encode(entity, context));
         }
         return result;
     }
@@ -69,15 +73,16 @@
     /**
      * Decodes the specified JSON array into a collection of entities.
      *
-     * @param json JSON array to decode
+     * @param json    JSON array to decode
+     * @param context decoding context
      * @return collection of decoded entities
      * @throws java.lang.UnsupportedOperationException if the codec does not
      *                                                 support decode operations
      */
-    public List<T> decode(ArrayNode json) {
+    public List<T> decode(ArrayNode json, CodecContext context) {
         List<T> result = new ArrayList<>();
         for (JsonNode node : json) {
-            result.add(decode((ObjectNode) node));
+            result.add(decode((ObjectNode) node, context));
         }
         return result;
     }
diff --git a/core/api/src/main/java/org/onlab/onos/net/link/LinkService.java b/core/api/src/main/java/org/onlab/onos/net/link/LinkService.java
index 70775f0..2039aa5 100644
--- a/core/api/src/main/java/org/onlab/onos/net/link/LinkService.java
+++ b/core/api/src/main/java/org/onlab/onos/net/link/LinkService.java
@@ -92,6 +92,8 @@
      */
     Set<Link> getIngressLinks(ConnectPoint connectPoint);
 
+    // FIXME: I don't think this makes sense; discuss and remove or adjust return
+    // to be a Set<Link> or add Link.Type parameter
     /**
      * Returns the infrastructure links between the specified source
      * and destination connection points.
diff --git a/core/api/src/test/java/org/onlab/onos/codec/JsonCodecTest.java b/core/api/src/test/java/org/onlab/onos/codec/JsonCodecTest.java
index f482a48..05460fb 100644
--- a/core/api/src/test/java/org/onlab/onos/codec/JsonCodecTest.java
+++ b/core/api/src/test/java/org/onlab/onos/codec/JsonCodecTest.java
@@ -58,12 +58,12 @@
 
     private static class FooCodec extends JsonCodec<Foo> {
         @Override
-        public ObjectNode encode(Foo entity, ObjectMapper mapper) {
-            return mapper.createObjectNode().put("name", entity.name);
+        public ObjectNode encode(Foo entity, CodecContext context) {
+            return context.mapper().createObjectNode().put("name", entity.name);
         }
 
         @Override
-        public Foo decode(ObjectNode json) {
+        public Foo decode(ObjectNode json, CodecContext context) {
             return new Foo(json.get("name").asText());
         }
     }
@@ -74,9 +74,26 @@
         Foo f2 = new Foo("bar");
         FooCodec codec = new FooCodec();
         ImmutableList<Foo> entities = ImmutableList.of(f1, f2);
-        ArrayNode json = codec.encode(entities, new ObjectMapper());
-        List<Foo> foos = codec.decode(json);
+        ArrayNode json = codec.encode(entities, new TestContext());
+        List<Foo> foos = codec.decode(json, new TestContext());
         assertEquals("incorrect encode/decode", entities, foos);
     }
 
+    private class TestContext implements CodecContext {
+        private ObjectMapper mapper = new ObjectMapper();
+        @Override
+        public ObjectMapper mapper() {
+            return mapper;
+        }
+
+        @Override
+        public <T> JsonCodec<T> codec(Class<T> entityClass) {
+            return null;
+        }
+
+        @Override
+        public <T> T get(Class<T> serviceClass) {
+            return null;
+        }
+    }
 }
\ No newline at end of file