Committed by
Yuta HIGUCHI
Add support to decode Device, Port, Link JSON.
- Device, Port, Link can now be encoded and decoded back to Java Object, which will be Object#equals to the original. - Modified DeviceServiceAdapter to be null-safe when possible - Modified JSON assertion/matcher not to check for exact number of attributes Change-Id: I7cf02e2254cf17f6265fb15847912519e564b14f
Showing
14 changed files
with
551 additions
and
31 deletions
| ... | @@ -17,12 +17,14 @@ package org.onosproject.net.device; | ... | @@ -17,12 +17,14 @@ package org.onosproject.net.device; |
| 17 | 17 | ||
| 18 | import com.google.common.base.Predicate; | 18 | import com.google.common.base.Predicate; |
| 19 | import com.google.common.collect.FluentIterable; | 19 | import com.google.common.collect.FluentIterable; |
| 20 | + | ||
| 20 | import org.onosproject.net.Device; | 21 | import org.onosproject.net.Device; |
| 21 | import org.onosproject.net.DeviceId; | 22 | import org.onosproject.net.DeviceId; |
| 22 | import org.onosproject.net.MastershipRole; | 23 | import org.onosproject.net.MastershipRole; |
| 23 | import org.onosproject.net.Port; | 24 | import org.onosproject.net.Port; |
| 24 | import org.onosproject.net.PortNumber; | 25 | import org.onosproject.net.PortNumber; |
| 25 | 26 | ||
| 27 | +import java.util.Collections; | ||
| 26 | import java.util.List; | 28 | import java.util.List; |
| 27 | 29 | ||
| 28 | /** | 30 | /** |
| ... | @@ -36,7 +38,7 @@ public class DeviceServiceAdapter implements DeviceService { | ... | @@ -36,7 +38,7 @@ public class DeviceServiceAdapter implements DeviceService { |
| 36 | 38 | ||
| 37 | @Override | 39 | @Override |
| 38 | public Iterable<Device> getDevices() { | 40 | public Iterable<Device> getDevices() { |
| 39 | - return null; | 41 | + return Collections.emptyList(); |
| 40 | } | 42 | } |
| 41 | 43 | ||
| 42 | @Override | 44 | @Override |
| ... | @@ -58,12 +60,12 @@ public class DeviceServiceAdapter implements DeviceService { | ... | @@ -58,12 +60,12 @@ public class DeviceServiceAdapter implements DeviceService { |
| 58 | 60 | ||
| 59 | @Override | 61 | @Override |
| 60 | public MastershipRole getRole(DeviceId deviceId) { | 62 | public MastershipRole getRole(DeviceId deviceId) { |
| 61 | - return null; | 63 | + return MastershipRole.NONE; |
| 62 | } | 64 | } |
| 63 | 65 | ||
| 64 | @Override | 66 | @Override |
| 65 | public List<Port> getPorts(DeviceId deviceId) { | 67 | public List<Port> getPorts(DeviceId deviceId) { |
| 66 | - return null; | 68 | + return Collections.emptyList(); |
| 67 | } | 69 | } |
| 68 | 70 | ||
| 69 | @Override | 71 | @Override | ... | ... |
| ... | @@ -16,10 +16,12 @@ | ... | @@ -16,10 +16,12 @@ |
| 16 | package org.onosproject.codec.impl; | 16 | package org.onosproject.codec.impl; |
| 17 | 17 | ||
| 18 | import com.fasterxml.jackson.databind.node.ObjectNode; | 18 | import com.fasterxml.jackson.databind.node.ObjectNode; |
| 19 | + | ||
| 19 | import org.onosproject.codec.CodecContext; | 20 | import org.onosproject.codec.CodecContext; |
| 20 | import org.onosproject.codec.JsonCodec; | 21 | import org.onosproject.codec.JsonCodec; |
| 21 | import org.onosproject.net.Annotated; | 22 | import org.onosproject.net.Annotated; |
| 22 | import org.onosproject.net.Annotations; | 23 | import org.onosproject.net.Annotations; |
| 24 | +import org.onosproject.net.DefaultAnnotations; | ||
| 23 | 25 | ||
| 24 | /** | 26 | /** |
| 25 | * Base JSON codec for annotated entities. | 27 | * Base JSON codec for annotated entities. |
| ... | @@ -42,4 +44,21 @@ public abstract class AnnotatedCodec<T extends Annotated> extends JsonCodec<T> { | ... | @@ -42,4 +44,21 @@ public abstract class AnnotatedCodec<T extends Annotated> extends JsonCodec<T> { |
| 42 | return node; | 44 | return node; |
| 43 | } | 45 | } |
| 44 | 46 | ||
| 47 | + /** | ||
| 48 | + * Extracts annotations of given Object. | ||
| 49 | + * | ||
| 50 | + * @param objNode annotated JSON object node | ||
| 51 | + * @param context decode context | ||
| 52 | + * @return extracted Annotations | ||
| 53 | + */ | ||
| 54 | + protected Annotations extractAnnotations(ObjectNode objNode, CodecContext context) { | ||
| 55 | + | ||
| 56 | + JsonCodec<Annotations> codec = context.codec(Annotations.class); | ||
| 57 | + if (objNode.has("annotations") && objNode.isObject()) { | ||
| 58 | + return codec.decode((ObjectNode) objNode.get("annotations"), context); | ||
| 59 | + } else { | ||
| 60 | + return DefaultAnnotations.EMPTY; | ||
| 61 | + } | ||
| 62 | + } | ||
| 63 | + | ||
| 45 | } | 64 | } | ... | ... |
| ... | @@ -16,9 +16,12 @@ | ... | @@ -16,9 +16,12 @@ |
| 16 | package org.onosproject.codec.impl; | 16 | package org.onosproject.codec.impl; |
| 17 | 17 | ||
| 18 | import com.fasterxml.jackson.databind.node.ObjectNode; | 18 | import com.fasterxml.jackson.databind.node.ObjectNode; |
| 19 | + | ||
| 19 | import org.onosproject.codec.CodecContext; | 20 | import org.onosproject.codec.CodecContext; |
| 20 | import org.onosproject.codec.JsonCodec; | 21 | import org.onosproject.codec.JsonCodec; |
| 21 | import org.onosproject.net.Annotations; | 22 | import org.onosproject.net.Annotations; |
| 23 | +import org.onosproject.net.DefaultAnnotations; | ||
| 24 | +import org.onosproject.net.DefaultAnnotations.Builder; | ||
| 22 | 25 | ||
| 23 | /** | 26 | /** |
| 24 | * Annotations JSON codec. | 27 | * Annotations JSON codec. |
| ... | @@ -34,4 +37,13 @@ public final class AnnotationsCodec extends JsonCodec<Annotations> { | ... | @@ -34,4 +37,13 @@ public final class AnnotationsCodec extends JsonCodec<Annotations> { |
| 34 | return result; | 37 | return result; |
| 35 | } | 38 | } |
| 36 | 39 | ||
| 40 | + @Override | ||
| 41 | + public Annotations decode(ObjectNode json, CodecContext context) { | ||
| 42 | + Builder builder = DefaultAnnotations.builder(); | ||
| 43 | + | ||
| 44 | + json.fields().forEachRemaining(e -> | ||
| 45 | + builder.set(e.getKey(), e.getValue().asText())); | ||
| 46 | + | ||
| 47 | + return builder.build(); | ||
| 48 | + } | ||
| 37 | } | 49 | } | ... | ... |
| ... | @@ -16,32 +16,59 @@ | ... | @@ -16,32 +16,59 @@ |
| 16 | package org.onosproject.codec.impl; | 16 | package org.onosproject.codec.impl; |
| 17 | 17 | ||
| 18 | import com.fasterxml.jackson.databind.node.ObjectNode; | 18 | import com.fasterxml.jackson.databind.node.ObjectNode; |
| 19 | + | ||
| 19 | import org.onosproject.codec.CodecContext; | 20 | import org.onosproject.codec.CodecContext; |
| 20 | import org.onosproject.codec.JsonCodec; | 21 | import org.onosproject.codec.JsonCodec; |
| 21 | import org.onosproject.net.ConnectPoint; | 22 | import org.onosproject.net.ConnectPoint; |
| 22 | import org.onosproject.net.DeviceId; | 23 | import org.onosproject.net.DeviceId; |
| 24 | +import org.onosproject.net.ElementId; | ||
| 23 | import org.onosproject.net.HostId; | 25 | import org.onosproject.net.HostId; |
| 26 | +import org.onosproject.net.PortNumber; | ||
| 24 | 27 | ||
| 25 | import static com.google.common.base.Preconditions.checkNotNull; | 28 | import static com.google.common.base.Preconditions.checkNotNull; |
| 29 | +import static org.onosproject.net.PortNumber.portNumber; | ||
| 26 | 30 | ||
| 27 | /** | 31 | /** |
| 28 | * Connection point JSON codec. | 32 | * Connection point JSON codec. |
| 29 | */ | 33 | */ |
| 30 | public final class ConnectPointCodec extends JsonCodec<ConnectPoint> { | 34 | public final class ConnectPointCodec extends JsonCodec<ConnectPoint> { |
| 31 | 35 | ||
| 36 | + // JSON field names | ||
| 37 | + private static final String ELEMENT_HOST = "host"; | ||
| 38 | + private static final String ELEMENT_DEVICE = "device"; | ||
| 39 | + private static final String PORT = "port"; | ||
| 40 | + | ||
| 32 | @Override | 41 | @Override |
| 33 | public ObjectNode encode(ConnectPoint point, CodecContext context) { | 42 | public ObjectNode encode(ConnectPoint point, CodecContext context) { |
| 34 | checkNotNull(point, "Connect point cannot be null"); | 43 | checkNotNull(point, "Connect point cannot be null"); |
| 35 | ObjectNode root = context.mapper().createObjectNode() | 44 | ObjectNode root = context.mapper().createObjectNode() |
| 36 | - .put("port", point.port().toString()); | 45 | + .put(PORT, point.port().toString()); |
| 37 | 46 | ||
| 38 | if (point.elementId() instanceof DeviceId) { | 47 | if (point.elementId() instanceof DeviceId) { |
| 39 | - root.put("device", point.deviceId().toString()); | 48 | + root.put(ELEMENT_DEVICE, point.deviceId().toString()); |
| 40 | } else if (point.elementId() instanceof HostId) { | 49 | } else if (point.elementId() instanceof HostId) { |
| 41 | - root.put("host", point.hostId().toString()); | 50 | + root.put(ELEMENT_HOST, point.hostId().toString()); |
| 42 | } | 51 | } |
| 43 | 52 | ||
| 44 | return root; | 53 | return root; |
| 45 | } | 54 | } |
| 46 | 55 | ||
| 56 | + @Override | ||
| 57 | + public ConnectPoint decode(ObjectNode json, CodecContext context) { | ||
| 58 | + if (json == null || !json.isObject()) { | ||
| 59 | + return null; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + ElementId elementId; | ||
| 63 | + if (json.has(ELEMENT_DEVICE)) { | ||
| 64 | + elementId = DeviceId.deviceId(json.get(ELEMENT_DEVICE).asText()); | ||
| 65 | + } else if (json.has(ELEMENT_HOST)) { | ||
| 66 | + elementId = HostId.hostId(json.get(ELEMENT_HOST).asText()); | ||
| 67 | + } else { | ||
| 68 | + // invalid JSON | ||
| 69 | + return null; | ||
| 70 | + } | ||
| 71 | + PortNumber portNumber = portNumber(json.get(PORT).asText()); | ||
| 72 | + return new ConnectPoint(elementId, portNumber); | ||
| 73 | + } | ||
| 47 | } | 74 | } | ... | ... |
| ... | @@ -16,32 +16,78 @@ | ... | @@ -16,32 +16,78 @@ |
| 16 | package org.onosproject.codec.impl; | 16 | package org.onosproject.codec.impl; |
| 17 | 17 | ||
| 18 | import com.fasterxml.jackson.databind.node.ObjectNode; | 18 | import com.fasterxml.jackson.databind.node.ObjectNode; |
| 19 | + | ||
| 20 | +import org.onlab.packet.ChassisId; | ||
| 19 | import org.onosproject.codec.CodecContext; | 21 | import org.onosproject.codec.CodecContext; |
| 22 | +import org.onosproject.net.Annotations; | ||
| 23 | +import org.onosproject.net.DefaultDevice; | ||
| 20 | import org.onosproject.net.Device; | 24 | import org.onosproject.net.Device; |
| 25 | +import org.onosproject.net.Device.Type; | ||
| 26 | +import org.onosproject.net.DeviceId; | ||
| 21 | import org.onosproject.net.device.DeviceService; | 27 | import org.onosproject.net.device.DeviceService; |
| 28 | +import org.onosproject.net.provider.ProviderId; | ||
| 22 | 29 | ||
| 23 | import static com.google.common.base.Preconditions.checkNotNull; | 30 | import static com.google.common.base.Preconditions.checkNotNull; |
| 31 | +import static org.onosproject.net.DeviceId.deviceId; | ||
| 24 | 32 | ||
| 25 | /** | 33 | /** |
| 26 | * Device JSON codec. | 34 | * Device JSON codec. |
| 27 | */ | 35 | */ |
| 28 | public final class DeviceCodec extends AnnotatedCodec<Device> { | 36 | public final class DeviceCodec extends AnnotatedCodec<Device> { |
| 29 | 37 | ||
| 38 | + // JSON fieldNames | ||
| 39 | + private static final String ID = "id"; | ||
| 40 | + private static final String TYPE = "type"; | ||
| 41 | + private static final String MFR = "mfr"; | ||
| 42 | + private static final String HW = "hw"; | ||
| 43 | + private static final String SW = "sw"; | ||
| 44 | + private static final String SERIAL = "serial"; | ||
| 45 | + private static final String CHASSIS_ID = "chassisId"; | ||
| 46 | + | ||
| 47 | + | ||
| 30 | @Override | 48 | @Override |
| 31 | public ObjectNode encode(Device device, CodecContext context) { | 49 | public ObjectNode encode(Device device, CodecContext context) { |
| 32 | checkNotNull(device, "Device cannot be null"); | 50 | checkNotNull(device, "Device cannot be null"); |
| 33 | DeviceService service = context.get(DeviceService.class); | 51 | DeviceService service = context.get(DeviceService.class); |
| 34 | ObjectNode result = context.mapper().createObjectNode() | 52 | ObjectNode result = context.mapper().createObjectNode() |
| 35 | - .put("id", device.id().toString()) | 53 | + .put(ID, device.id().toString()) |
| 36 | - .put("type", device.type().name()) | 54 | + .put(TYPE, device.type().name()) |
| 37 | .put("available", service.isAvailable(device.id())) | 55 | .put("available", service.isAvailable(device.id())) |
| 38 | .put("role", service.getRole(device.id()).toString()) | 56 | .put("role", service.getRole(device.id()).toString()) |
| 39 | - .put("mfr", device.manufacturer()) | 57 | + .put(MFR, device.manufacturer()) |
| 40 | - .put("hw", device.hwVersion()) | 58 | + .put(HW, device.hwVersion()) |
| 41 | - .put("sw", device.swVersion()) | 59 | + .put(SW, device.swVersion()) |
| 42 | - .put("serial", device.serialNumber()) | 60 | + .put(SERIAL, device.serialNumber()) |
| 43 | - .put("chassisId", device.chassisId().toString()); | 61 | + .put(CHASSIS_ID, device.chassisId().toString()); |
| 44 | return annotate(result, device, context); | 62 | return annotate(result, device, context); |
| 45 | } | 63 | } |
| 46 | 64 | ||
| 65 | + | ||
| 66 | + /** | ||
| 67 | + * {@inheritDoc} | ||
| 68 | + * | ||
| 69 | + * Note: ProviderId is not part of JSON representation. | ||
| 70 | + * Returned object will have random ProviderId set. | ||
| 71 | + */ | ||
| 72 | + @Override | ||
| 73 | + public Device decode(ObjectNode json, CodecContext context) { | ||
| 74 | + if (json == null || !json.isObject()) { | ||
| 75 | + return null; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + DeviceId id = deviceId(json.get(ID).asText()); | ||
| 79 | + // TODO: add providerId to JSON if we need to recover them. | ||
| 80 | + ProviderId pid = new ProviderId(id.uri().getScheme(), "DeviceCodec"); | ||
| 81 | + | ||
| 82 | + Type type = Type.valueOf(json.get(TYPE).asText()); | ||
| 83 | + String mfr = json.get(MFR).asText(); | ||
| 84 | + String hw = json.get(HW).asText(); | ||
| 85 | + String sw = json.get(SW).asText(); | ||
| 86 | + String serial = json.get(SERIAL).asText(); | ||
| 87 | + ChassisId chassisId = new ChassisId(json.get(CHASSIS_ID).asText()); | ||
| 88 | + Annotations annotations = extractAnnotations(json, context); | ||
| 89 | + | ||
| 90 | + return new DefaultDevice(pid, id, type, mfr, hw, sw, serial, | ||
| 91 | + chassisId, annotations); | ||
| 92 | + } | ||
| 47 | } | 93 | } | ... | ... |
| ... | @@ -16,11 +16,15 @@ | ... | @@ -16,11 +16,15 @@ |
| 16 | package org.onosproject.codec.impl; | 16 | package org.onosproject.codec.impl; |
| 17 | 17 | ||
| 18 | import com.fasterxml.jackson.databind.node.ObjectNode; | 18 | import com.fasterxml.jackson.databind.node.ObjectNode; |
| 19 | + | ||
| 19 | import org.onosproject.codec.CodecContext; | 20 | import org.onosproject.codec.CodecContext; |
| 20 | import org.onosproject.codec.JsonCodec; | 21 | import org.onosproject.codec.JsonCodec; |
| 22 | +import org.onosproject.net.Annotations; | ||
| 21 | import org.onosproject.net.ConnectPoint; | 23 | import org.onosproject.net.ConnectPoint; |
| 24 | +import org.onosproject.net.DefaultLink; | ||
| 22 | import org.onosproject.net.Link; | 25 | import org.onosproject.net.Link; |
| 23 | -import org.onosproject.net.device.DeviceService; | 26 | +import org.onosproject.net.Link.Type; |
| 27 | +import org.onosproject.net.provider.ProviderId; | ||
| 24 | 28 | ||
| 25 | import static com.google.common.base.Preconditions.checkNotNull; | 29 | import static com.google.common.base.Preconditions.checkNotNull; |
| 26 | 30 | ||
| ... | @@ -29,15 +33,44 @@ import static com.google.common.base.Preconditions.checkNotNull; | ... | @@ -29,15 +33,44 @@ import static com.google.common.base.Preconditions.checkNotNull; |
| 29 | */ | 33 | */ |
| 30 | public final class LinkCodec extends AnnotatedCodec<Link> { | 34 | public final class LinkCodec extends AnnotatedCodec<Link> { |
| 31 | 35 | ||
| 36 | + // JSON field names | ||
| 37 | + private static final String SRC = "src"; | ||
| 38 | + private static final String DST = "dst"; | ||
| 39 | + private static final String TYPE = "type"; | ||
| 40 | + | ||
| 32 | @Override | 41 | @Override |
| 33 | public ObjectNode encode(Link link, CodecContext context) { | 42 | public ObjectNode encode(Link link, CodecContext context) { |
| 34 | checkNotNull(link, "Link cannot be null"); | 43 | checkNotNull(link, "Link cannot be null"); |
| 35 | - DeviceService service = context.get(DeviceService.class); | ||
| 36 | JsonCodec<ConnectPoint> codec = context.codec(ConnectPoint.class); | 44 | JsonCodec<ConnectPoint> codec = context.codec(ConnectPoint.class); |
| 37 | ObjectNode result = context.mapper().createObjectNode(); | 45 | ObjectNode result = context.mapper().createObjectNode(); |
| 38 | - result.set("src", codec.encode(link.src(), context)); | 46 | + result.set(SRC, codec.encode(link.src(), context)); |
| 39 | - result.set("dst", codec.encode(link.dst(), context)); | 47 | + result.set(DST, codec.encode(link.dst(), context)); |
| 48 | + result.put(TYPE, link.type().toString()); | ||
| 40 | return annotate(result, link, context); | 49 | return annotate(result, link, context); |
| 41 | } | 50 | } |
| 42 | 51 | ||
| 52 | + | ||
| 53 | + /** | ||
| 54 | + * {@inheritDoc} | ||
| 55 | + * | ||
| 56 | + * Note: ProviderId is not part of JSON representation. | ||
| 57 | + * Returned object will have random ProviderId set. | ||
| 58 | + */ | ||
| 59 | + @Override | ||
| 60 | + public Link decode(ObjectNode json, CodecContext context) { | ||
| 61 | + if (json == null || !json.isObject()) { | ||
| 62 | + return null; | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + JsonCodec<ConnectPoint> codec = context.codec(ConnectPoint.class); | ||
| 66 | + // TODO: add providerId to JSON if we need to recover them. | ||
| 67 | + ProviderId pid = new ProviderId("json", "LinkCodec"); | ||
| 68 | + | ||
| 69 | + ConnectPoint src = codec.decode((ObjectNode) json.get(SRC), context); | ||
| 70 | + ConnectPoint dst = codec.decode((ObjectNode) json.get(DST), context); | ||
| 71 | + Type type = Type.valueOf(json.get(TYPE).asText()); | ||
| 72 | + Annotations annotations = extractAnnotations(json, context); | ||
| 73 | + | ||
| 74 | + return new DefaultLink(pid, src, dst, type, annotations); | ||
| 75 | + } | ||
| 43 | } | 76 | } | ... | ... |
| ... | @@ -16,9 +16,18 @@ | ... | @@ -16,9 +16,18 @@ |
| 16 | package org.onosproject.codec.impl; | 16 | package org.onosproject.codec.impl; |
| 17 | 17 | ||
| 18 | import com.fasterxml.jackson.databind.node.ObjectNode; | 18 | import com.fasterxml.jackson.databind.node.ObjectNode; |
| 19 | + | ||
| 20 | +import org.onlab.packet.ChassisId; | ||
| 19 | import org.onosproject.codec.CodecContext; | 21 | import org.onosproject.codec.CodecContext; |
| 22 | +import org.onosproject.net.Annotations; | ||
| 23 | +import org.onosproject.net.DefaultAnnotations; | ||
| 24 | +import org.onosproject.net.DefaultPort; | ||
| 25 | +import org.onosproject.net.Device; | ||
| 26 | +import org.onosproject.net.DeviceId; | ||
| 20 | import org.onosproject.net.Port; | 27 | import org.onosproject.net.Port; |
| 28 | +import org.onosproject.net.Port.Type; | ||
| 21 | import org.onosproject.net.PortNumber; | 29 | import org.onosproject.net.PortNumber; |
| 30 | +import org.onosproject.net.provider.ProviderId; | ||
| 22 | 31 | ||
| 23 | import static com.google.common.base.Preconditions.checkNotNull; | 32 | import static com.google.common.base.Preconditions.checkNotNull; |
| 24 | 33 | ||
| ... | @@ -27,19 +36,125 @@ import static com.google.common.base.Preconditions.checkNotNull; | ... | @@ -27,19 +36,125 @@ import static com.google.common.base.Preconditions.checkNotNull; |
| 27 | */ | 36 | */ |
| 28 | public final class PortCodec extends AnnotatedCodec<Port> { | 37 | public final class PortCodec extends AnnotatedCodec<Port> { |
| 29 | 38 | ||
| 39 | + // JSON field names | ||
| 40 | + private static final String ELEMENT = "element"; // DeviceId | ||
| 41 | + private static final String PORT_NAME = "port"; | ||
| 42 | + private static final String IS_ENABLED = "isEnabled"; | ||
| 43 | + private static final String TYPE = "type"; | ||
| 44 | + private static final String PORT_SPEED = "portSpeed"; | ||
| 45 | + | ||
| 46 | + // Special port name alias | ||
| 47 | + private static final String PORT_NAME_LOCAL = "local"; | ||
| 48 | + | ||
| 30 | @Override | 49 | @Override |
| 31 | public ObjectNode encode(Port port, CodecContext context) { | 50 | public ObjectNode encode(Port port, CodecContext context) { |
| 32 | checkNotNull(port, "Port cannot be null"); | 51 | checkNotNull(port, "Port cannot be null"); |
| 33 | ObjectNode result = context.mapper().createObjectNode() | 52 | ObjectNode result = context.mapper().createObjectNode() |
| 34 | - .put("port", portName(port.number())) | 53 | + .put(ELEMENT, port.element().id().toString()) |
| 35 | - .put("isEnabled", port.isEnabled()) | 54 | + .put(PORT_NAME, portName(port.number())) |
| 36 | - .put("type", port.type().toString().toLowerCase()) | 55 | + .put(IS_ENABLED, port.isEnabled()) |
| 37 | - .put("portSpeed", port.portSpeed()); | 56 | + .put(TYPE, port.type().toString().toLowerCase()) |
| 57 | + .put(PORT_SPEED, port.portSpeed()); | ||
| 38 | return annotate(result, port, context); | 58 | return annotate(result, port, context); |
| 39 | } | 59 | } |
| 40 | 60 | ||
| 41 | private String portName(PortNumber port) { | 61 | private String portName(PortNumber port) { |
| 42 | - return port.equals(PortNumber.LOCAL) ? "local" : port.toString(); | 62 | + return port.equals(PortNumber.LOCAL) ? PORT_NAME_LOCAL : port.toString(); |
| 63 | + } | ||
| 64 | + | ||
| 65 | + private static PortNumber portNumber(String portName) { | ||
| 66 | + if (portName.equalsIgnoreCase(PORT_NAME_LOCAL)) { | ||
| 67 | + return PortNumber.LOCAL; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + return PortNumber.portNumber(portName); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + | ||
| 74 | + /** | ||
| 75 | + * {@inheritDoc} | ||
| 76 | + * | ||
| 77 | + * Note: Result of {@link Port#element()} returned Port object, | ||
| 78 | + * is not a full Device object. | ||
| 79 | + * Only it's DeviceId can be used. | ||
| 80 | + */ | ||
| 81 | + @Override | ||
| 82 | + public Port decode(ObjectNode json, CodecContext context) { | ||
| 83 | + if (json == null || !json.isObject()) { | ||
| 84 | + return null; | ||
| 43 | } | 85 | } |
| 44 | 86 | ||
| 87 | + DeviceId did = DeviceId.deviceId(json.get(ELEMENT).asText()); | ||
| 88 | + Device device = new DummyDevice(did); | ||
| 89 | + PortNumber number = portNumber(json.get(PORT_NAME).asText()); | ||
| 90 | + boolean isEnabled = json.get(IS_ENABLED).asBoolean(); | ||
| 91 | + Type type = Type.valueOf(json.get(TYPE).asText().toUpperCase()); | ||
| 92 | + long portSpeed = json.get(PORT_SPEED).asLong(); | ||
| 93 | + Annotations annotations = extractAnnotations(json, context); | ||
| 94 | + | ||
| 95 | + return new DefaultPort(device, number, isEnabled, type, portSpeed, annotations); | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + | ||
| 99 | + /** | ||
| 100 | + * Dummy Device which only holds DeviceId. | ||
| 101 | + */ | ||
| 102 | + private static final class DummyDevice implements Device { | ||
| 103 | + | ||
| 104 | + private final DeviceId did; | ||
| 105 | + | ||
| 106 | + /** | ||
| 107 | + * Constructs Dummy Device which only holds DeviceId. | ||
| 108 | + * | ||
| 109 | + * @param did device Id | ||
| 110 | + */ | ||
| 111 | + public DummyDevice(DeviceId did) { | ||
| 112 | + this.did = did; | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + @Override | ||
| 116 | + public Annotations annotations() { | ||
| 117 | + return DefaultAnnotations.EMPTY; | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + @Override | ||
| 121 | + public ProviderId providerId() { | ||
| 122 | + return new ProviderId(did.uri().getScheme(), "PortCodec"); | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + @Override | ||
| 126 | + public DeviceId id() { | ||
| 127 | + return did; | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | + @Override | ||
| 131 | + public Type type() { | ||
| 132 | + return Type.SWITCH; | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + @Override | ||
| 136 | + public String manufacturer() { | ||
| 137 | + return "dummy"; | ||
| 138 | + } | ||
| 139 | + | ||
| 140 | + @Override | ||
| 141 | + public String hwVersion() { | ||
| 142 | + return "0"; | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + @Override | ||
| 146 | + public String swVersion() { | ||
| 147 | + return "0"; | ||
| 148 | + } | ||
| 149 | + | ||
| 150 | + @Override | ||
| 151 | + public String serialNumber() { | ||
| 152 | + return "0"; | ||
| 153 | + } | ||
| 154 | + | ||
| 155 | + @Override | ||
| 156 | + public ChassisId chassisId() { | ||
| 157 | + return new ChassisId(); | ||
| 158 | + } | ||
| 159 | + } | ||
| 45 | } | 160 | } | ... | ... |
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +package org.onosproject.codec.impl; | ||
| 18 | + | ||
| 19 | +import static org.hamcrest.MatcherAssert.assertThat; | ||
| 20 | +import static org.hamcrest.Matchers.notNullValue; | ||
| 21 | +import static org.hamcrest.Matchers.is; | ||
| 22 | +import static org.onosproject.codec.impl.JsonCodecUtils.assertJsonEncodable; | ||
| 23 | + | ||
| 24 | +import org.junit.Test; | ||
| 25 | +import org.onosproject.codec.JsonCodec; | ||
| 26 | +import org.onosproject.net.DefaultDevice; | ||
| 27 | +import org.onosproject.net.Device; | ||
| 28 | +import org.onosproject.net.device.DeviceService; | ||
| 29 | +import org.onosproject.net.device.DeviceServiceAdapter; | ||
| 30 | + | ||
| 31 | +/** | ||
| 32 | + * Unit test for DeviceCodec. | ||
| 33 | + */ | ||
| 34 | +public class DeviceCodecTest { | ||
| 35 | + | ||
| 36 | + private Device device = new DefaultDevice(JsonCodecUtils.PID, | ||
| 37 | + JsonCodecUtils.DID1, | ||
| 38 | + Device.Type.SWITCH, | ||
| 39 | + JsonCodecUtils.MFR, | ||
| 40 | + JsonCodecUtils.HW, | ||
| 41 | + JsonCodecUtils.SW1, | ||
| 42 | + JsonCodecUtils.SN, | ||
| 43 | + JsonCodecUtils.CID, | ||
| 44 | + JsonCodecUtils.A1); | ||
| 45 | + | ||
| 46 | + | ||
| 47 | + | ||
| 48 | + @Test | ||
| 49 | + public void deviceCodecTest() { | ||
| 50 | + final MockCodecContext context = new MockCodecContext(); | ||
| 51 | + context.registerService(DeviceService.class, new DeviceServiceAdapter()); | ||
| 52 | + final JsonCodec<Device> codec = context.codec(Device.class); | ||
| 53 | + assertThat(codec, is(notNullValue())); | ||
| 54 | + final Device pojoIn = device; | ||
| 55 | + | ||
| 56 | + assertJsonEncodable(context, codec, pojoIn); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +package org.onosproject.codec.impl; | ||
| 18 | + | ||
| 19 | +import static org.hamcrest.MatcherAssert.assertThat; | ||
| 20 | +import static org.hamcrest.Matchers.is; | ||
| 21 | +import static org.hamcrest.Matchers.notNullValue; | ||
| 22 | +import static org.junit.Assert.assertEquals; | ||
| 23 | +import static org.onosproject.net.DeviceId.deviceId; | ||
| 24 | + | ||
| 25 | +import org.onlab.packet.ChassisId; | ||
| 26 | +import org.onosproject.codec.CodecContext; | ||
| 27 | +import org.onosproject.codec.JsonCodec; | ||
| 28 | +import org.onosproject.net.ConnectPoint; | ||
| 29 | +import org.onosproject.net.DefaultAnnotations; | ||
| 30 | +import org.onosproject.net.DeviceId; | ||
| 31 | +import org.onosproject.net.PortNumber; | ||
| 32 | +import org.onosproject.net.SparseAnnotations; | ||
| 33 | +import org.onosproject.net.provider.ProviderId; | ||
| 34 | + | ||
| 35 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 36 | + | ||
| 37 | +/** | ||
| 38 | + * JsonCodec test utilities. | ||
| 39 | + */ | ||
| 40 | +public abstract class JsonCodecUtils { | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * Checks if given Object can be encoded to JSON and back. | ||
| 44 | + * | ||
| 45 | + * @param context CodecContext | ||
| 46 | + * @param codec JsonCodec | ||
| 47 | + * @param pojoIn Java Object to encode. | ||
| 48 | + * Object is expected to have #equals implemented. | ||
| 49 | + */ | ||
| 50 | + public static <T> void assertJsonEncodable(final CodecContext context, | ||
| 51 | + final JsonCodec<T> codec, | ||
| 52 | + final T pojoIn) { | ||
| 53 | + final ObjectNode json = codec.encode(pojoIn, context); | ||
| 54 | + | ||
| 55 | + assertThat(json, is(notNullValue())); | ||
| 56 | + | ||
| 57 | + final T pojoOut = codec.decode(json, context); | ||
| 58 | + assertThat(pojoOut, is(notNullValue())); | ||
| 59 | + | ||
| 60 | + assertEquals(pojoIn, pojoOut); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + static final ProviderId PID = new ProviderId("of", "foo"); | ||
| 64 | + static final ProviderId PIDA = new ProviderId("of", "bar", true); | ||
| 65 | + static final DeviceId DID1 = deviceId("of:foo"); | ||
| 66 | + static final DeviceId DID2 = deviceId("of:bar"); | ||
| 67 | + static final String MFR = "whitebox"; | ||
| 68 | + static final String HW = "1.1.x"; | ||
| 69 | + static final String SW1 = "3.8.1"; | ||
| 70 | + static final String SW2 = "3.9.5"; | ||
| 71 | + static final String SN = "43311-12345"; | ||
| 72 | + static final ChassisId CID = new ChassisId(); | ||
| 73 | + static final PortNumber P1 = PortNumber.portNumber(1); | ||
| 74 | + static final PortNumber P2 = PortNumber.portNumber(2); | ||
| 75 | + static final PortNumber P3 = PortNumber.portNumber(3); | ||
| 76 | + static final SparseAnnotations A1 = DefaultAnnotations.builder() | ||
| 77 | + .set("A1", "a1") | ||
| 78 | + .set("B1", "b1") | ||
| 79 | + .build(); | ||
| 80 | + static final ConnectPoint CP1 = new ConnectPoint(DID1, P1); | ||
| 81 | + static final ConnectPoint CP2 = new ConnectPoint(DID2, P2); | ||
| 82 | + | ||
| 83 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +package org.onosproject.codec.impl; | ||
| 18 | + | ||
| 19 | +import static org.hamcrest.MatcherAssert.assertThat; | ||
| 20 | +import static org.hamcrest.Matchers.is; | ||
| 21 | +import static org.hamcrest.Matchers.notNullValue; | ||
| 22 | +import static org.onosproject.codec.impl.JsonCodecUtils.assertJsonEncodable; | ||
| 23 | + | ||
| 24 | +import org.junit.Test; | ||
| 25 | +import org.onosproject.codec.JsonCodec; | ||
| 26 | +import org.onosproject.net.DefaultLink; | ||
| 27 | +import org.onosproject.net.Link; | ||
| 28 | +import org.onosproject.net.device.DeviceService; | ||
| 29 | +import org.onosproject.net.device.DeviceServiceAdapter; | ||
| 30 | + | ||
| 31 | +/** | ||
| 32 | + * Unit test for LinkCodec. | ||
| 33 | + */ | ||
| 34 | +public class LinkCodecTest { | ||
| 35 | + | ||
| 36 | + private final Link link = new DefaultLink(JsonCodecUtils.PID, | ||
| 37 | + JsonCodecUtils.CP1, | ||
| 38 | + JsonCodecUtils.CP2, | ||
| 39 | + Link.Type.DIRECT, | ||
| 40 | + Link.State.ACTIVE, | ||
| 41 | + false, | ||
| 42 | + JsonCodecUtils.A1); | ||
| 43 | + | ||
| 44 | + @Test | ||
| 45 | + public void linkCodecTest() { | ||
| 46 | + final MockCodecContext context = new MockCodecContext(); | ||
| 47 | + context.registerService(DeviceService.class, new DeviceServiceAdapter()); | ||
| 48 | + final JsonCodec<Link> codec = context.codec(Link.class); | ||
| 49 | + assertThat(codec, is(notNullValue())); | ||
| 50 | + final Link pojoIn = link; | ||
| 51 | + | ||
| 52 | + assertJsonEncodable(context, codec, pojoIn); | ||
| 53 | + } | ||
| 54 | +} |
| ... | @@ -15,6 +15,9 @@ | ... | @@ -15,6 +15,9 @@ |
| 15 | */ | 15 | */ |
| 16 | package org.onosproject.codec.impl; | 16 | package org.onosproject.codec.impl; |
| 17 | 17 | ||
| 18 | +import java.util.HashMap; | ||
| 19 | +import java.util.Map; | ||
| 20 | + | ||
| 18 | import org.onosproject.codec.CodecContext; | 21 | import org.onosproject.codec.CodecContext; |
| 19 | import org.onosproject.codec.JsonCodec; | 22 | import org.onosproject.codec.JsonCodec; |
| 20 | 23 | ||
| ... | @@ -25,8 +28,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; | ... | @@ -25,8 +28,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; |
| 25 | */ | 28 | */ |
| 26 | public class MockCodecContext implements CodecContext { | 29 | public class MockCodecContext implements CodecContext { |
| 27 | 30 | ||
| 28 | - private ObjectMapper mapper = new ObjectMapper(); | 31 | + private final ObjectMapper mapper = new ObjectMapper(); |
| 29 | - private CodecManager manager = new CodecManager(); | 32 | + private final CodecManager manager = new CodecManager(); |
| 33 | + private final Map<Class<? extends Object>, Object> services = new HashMap<>(); | ||
| 30 | 34 | ||
| 31 | /** | 35 | /** |
| 32 | * Constructs a new mock codec context. | 36 | * Constructs a new mock codec context. |
| ... | @@ -46,9 +50,15 @@ public class MockCodecContext implements CodecContext { | ... | @@ -46,9 +50,15 @@ public class MockCodecContext implements CodecContext { |
| 46 | return manager.getCodec(entityClass); | 50 | return manager.getCodec(entityClass); |
| 47 | } | 51 | } |
| 48 | 52 | ||
| 53 | + @SuppressWarnings("unchecked") | ||
| 49 | @Override | 54 | @Override |
| 50 | public <T> T get(Class<T> serviceClass) { | 55 | public <T> T get(Class<T> serviceClass) { |
| 51 | - return null; | 56 | + return (T) services.get(serviceClass); |
| 57 | + } | ||
| 58 | + | ||
| 59 | + // for registering mock services | ||
| 60 | + public <T> void registerService(Class<T> serviceClass, T impl) { | ||
| 61 | + services.put(serviceClass, impl); | ||
| 52 | } | 62 | } |
| 53 | 63 | ||
| 54 | } | 64 | } | ... | ... |
| 1 | +/* | ||
| 2 | + * Copyright 2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +package org.onosproject.codec.impl; | ||
| 18 | + | ||
| 19 | +import static org.hamcrest.MatcherAssert.assertThat; | ||
| 20 | +import static org.hamcrest.Matchers.is; | ||
| 21 | +import static org.hamcrest.Matchers.notNullValue; | ||
| 22 | +import static org.onosproject.codec.impl.JsonCodecUtils.assertJsonEncodable; | ||
| 23 | + | ||
| 24 | +import org.junit.Test; | ||
| 25 | +import org.onosproject.codec.JsonCodec; | ||
| 26 | +import org.onosproject.net.DefaultDevice; | ||
| 27 | +import org.onosproject.net.DefaultPort; | ||
| 28 | +import org.onosproject.net.Device; | ||
| 29 | +import org.onosproject.net.Port; | ||
| 30 | +import org.onosproject.net.device.DeviceService; | ||
| 31 | +import org.onosproject.net.device.DeviceServiceAdapter; | ||
| 32 | + | ||
| 33 | +/** | ||
| 34 | + * Unit test for PortCodec. | ||
| 35 | + */ | ||
| 36 | +public class PortCodecTest { | ||
| 37 | + | ||
| 38 | + | ||
| 39 | + | ||
| 40 | + private final Device device = new DefaultDevice(JsonCodecUtils.PID, | ||
| 41 | + JsonCodecUtils.DID1, | ||
| 42 | + Device.Type.SWITCH, | ||
| 43 | + JsonCodecUtils.MFR, | ||
| 44 | + JsonCodecUtils.HW, | ||
| 45 | + JsonCodecUtils.SW1, | ||
| 46 | + JsonCodecUtils.SN, | ||
| 47 | + JsonCodecUtils.CID, | ||
| 48 | + JsonCodecUtils.A1); | ||
| 49 | + | ||
| 50 | + private final Port port = new DefaultPort(device, | ||
| 51 | + JsonCodecUtils.P1, | ||
| 52 | + true, | ||
| 53 | + JsonCodecUtils.A1); | ||
| 54 | + | ||
| 55 | + @Test | ||
| 56 | + public void portCodecTest() { | ||
| 57 | + final MockCodecContext context = new MockCodecContext(); | ||
| 58 | + context.registerService(DeviceService.class, new DeviceServiceAdapter()); | ||
| 59 | + final JsonCodec<Port> codec = context.codec(Port.class); | ||
| 60 | + assertThat(codec, is(notNullValue())); | ||
| 61 | + final Port pojoIn = port; | ||
| 62 | + | ||
| 63 | + assertJsonEncodable(context, codec, pojoIn); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | +} |
| ... | @@ -343,7 +343,6 @@ public class DevicesResourceTest extends ResourceTest { | ... | @@ -343,7 +343,6 @@ public class DevicesResourceTest extends ResourceTest { |
| 343 | for (int portIndex = 0; portIndex < jsonPorts.size(); portIndex++) { | 343 | for (int portIndex = 0; portIndex < jsonPorts.size(); portIndex++) { |
| 344 | JsonObject jsonPort = jsonPorts.get(portIndex).asObject(); | 344 | JsonObject jsonPort = jsonPorts.get(portIndex).asObject(); |
| 345 | 345 | ||
| 346 | - assertThat(jsonPort.size(), is(4)); | ||
| 347 | assertThat(jsonPort.get("port").asString(), | 346 | assertThat(jsonPort.get("port").asString(), |
| 348 | is(Integer.toString(portIndex + 1))); | 347 | is(Integer.toString(portIndex + 1))); |
| 349 | assertThat(jsonPort.get("isEnabled").asBoolean(), | 348 | assertThat(jsonPort.get("isEnabled").asBoolean(), | ... | ... |
| ... | @@ -123,11 +123,6 @@ public class LinksResourceTest extends ResourceTest { | ... | @@ -123,11 +123,6 @@ public class LinksResourceTest extends ResourceTest { |
| 123 | 123 | ||
| 124 | JsonObject jsonLink = json.get(jsonLinkIndex).asObject(); | 124 | JsonObject jsonLink = json.get(jsonLinkIndex).asObject(); |
| 125 | 125 | ||
| 126 | - if (jsonLink.names().size() != expectedAttributes) { | ||
| 127 | - reason = "Found a link with the wrong number of attributes"; | ||
| 128 | - return false; | ||
| 129 | - } | ||
| 130 | - | ||
| 131 | if (matchesLink(link).matchesSafely(jsonLink)) { | 126 | if (matchesLink(link).matchesSafely(jsonLink)) { |
| 132 | return true; | 127 | return true; |
| 133 | } | 128 | } | ... | ... |
-
Please register or login to post a comment