Ray Milkey
Committed by Gerrit Code Review

ONOS-743 - Use REST API Codecs to generate JSON for CLI commands

Change-Id: I25e0840d1af03341c638f837498c95275e6cf31b
Showing 23 changed files with 134 additions and 296 deletions
......@@ -41,6 +41,10 @@
<groupId>org.onosproject</groupId>
<artifactId>onlab-osgi</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-core-common</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
......
......@@ -15,20 +15,24 @@
*/
package org.onosproject.cli;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.karaf.shell.commands.Option;
import org.apache.karaf.shell.console.AbstractAction;
import org.onlab.osgi.DefaultServiceDirectory;
import org.onlab.osgi.ServiceNotFoundException;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.JsonCodec;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.Annotations;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Base abstraction of Karaf shell commands.
*/
public abstract class AbstractShellCommand extends AbstractAction {
public abstract class AbstractShellCommand extends AbstractAction implements CodecContext {
@Option(name = "-j", aliases = "--json", description = "Output JSON",
required = false, multiValued = false)
......@@ -129,4 +133,35 @@ public abstract class AbstractShellCommand extends AbstractAction {
return null;
}
private final ObjectMapper mapper = new ObjectMapper();
@Override
public ObjectMapper mapper() {
return mapper;
}
@Override
@SuppressWarnings("unchecked")
public <T> JsonCodec<T> codec(Class<T> entityClass) {
return get(CodecService.class).getCodec(entityClass);
}
@Override
public <T> T getService(Class<T> serviceClass) {
return get(serviceClass);
}
/**
* Generates a Json representation of an object.
*
* @param entity object to generate JSON for
* @param entityClass class to format with - this chooses which codec to use
* @param <T> Type of the object being formatted
* @return JSON object representation
*/
public <T> ObjectNode jsonForEntity(T entity, Class<T> entityClass) {
return codec(entityClass).encode(entity, this);
}
}
......
......@@ -15,9 +15,9 @@
*/
package org.onosproject.cli.app;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.util.Collections;
import java.util.List;
import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.commands.Option;
import org.onosproject.app.ApplicationService;
......@@ -25,8 +25,9 @@ import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cli.Comparators;
import org.onosproject.core.Application;
import java.util.Collections;
import java.util.List;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import static com.google.common.collect.Lists.newArrayList;
import static org.onosproject.app.ApplicationState.ACTIVE;
......@@ -88,25 +89,12 @@ public class ApplicationsListCommand extends AbstractShellCommand {
for (Application app : apps) {
boolean isActive = service.getState(app.id()) == ACTIVE;
if (activeOnly && isActive || !activeOnly) {
result.add(json(service, mapper, app));
result.add(jsonForEntity(app, Application.class));
}
}
return result;
}
protected JsonNode json(ApplicationService service, ObjectMapper mapper,
Application app) {
return mapper.createObjectNode()
.put("name", app.id().name())
.put("id", app.id().id())
.put("version", app.version().toString())
.put("description", app.description())
.put("origin", app.origin())
.put("permissions", app.permissions().toString())
.put("featuresRepo", app.featuresRepo().isPresent() ?
app.featuresRepo().get().toString() : "")
.put("features", app.features().toString())
.put("state", service.getState(app.id()).toString());
}
}
......
......@@ -43,7 +43,7 @@ public class ClusterLinksCommand extends ClustersListCommand {
if (cluster == null) {
error("No such cluster %s", cid);
} else if (outputJson()) {
print("%s", json(service.getClusterLinks(topology, cluster)));
print("%s", json(this, service.getClusterLinks(topology, cluster)));
} else {
for (Link link : service.getClusterLinks(topology, cluster)) {
print(linkString(link));
......
......@@ -55,12 +55,11 @@ public class ClustersListCommand extends TopologyCommand {
private JsonNode json(Iterable<TopologyCluster> clusters) {
ObjectMapper mapper = new ObjectMapper();
ArrayNode result = mapper.createArrayNode();
for (TopologyCluster cluster : clusters) {
result.add(mapper.createObjectNode()
.put("id", cluster.id().index())
.put("deviceCount", cluster.deviceCount())
.put("linkCount", cluster.linkCount()));
}
clusters.spliterator()
.forEachRemaining(cluster ->
result.add(jsonForEntity(cluster, TopologyCluster.class)));
return result;
}
......
......@@ -116,7 +116,7 @@ public class DevicePortsListCommand extends DevicesListCommand {
.set("annotations", annotations(mapper, port.annotations())));
}
}
result.set("device", json(service, mapper, device));
result.set("device", jsonForEntity(device, Device.class));
result.set("ports", ports);
return result;
}
......
......@@ -15,18 +15,18 @@
*/
package org.onosproject.cli.net;
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;
import java.util.Collections;
import java.util.List;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cli.Comparators;
import org.onosproject.net.Device;
import org.onosproject.net.device.DeviceService;
import java.util.Collections;
import java.util.List;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import static com.google.common.collect.Lists.newArrayList;
......@@ -44,7 +44,7 @@ public class DevicesListCommand extends AbstractShellCommand {
protected void execute() {
DeviceService service = get(DeviceService.class);
if (outputJson()) {
print("%s", json(service, getSortedDevices(service)));
print("%s", json(getSortedDevices(service)));
} else {
for (Device device : getSortedDevices(service)) {
printDevice(service, device);
......@@ -55,40 +55,14 @@ public class DevicesListCommand extends AbstractShellCommand {
/**
* Returns JSON node representing the specified devices.
*
* @param service device service
* @param devices collection of devices
* @return JSON node
*/
public static JsonNode json(DeviceService service, Iterable<Device> devices) {
private JsonNode json(Iterable<Device> devices) {
ObjectMapper mapper = new ObjectMapper();
ArrayNode result = mapper.createArrayNode();
for (Device device : devices) {
result.add(json(service, mapper, device));
}
return result;
}
/**
* Returns JSON node representing the specified device.
*
* @param service device service
* @param mapper object mapper
* @param device infrastructure device
* @return JSON node
*/
public static ObjectNode json(DeviceService service, ObjectMapper mapper,
Device device) {
ObjectNode result = mapper.createObjectNode();
if (device != null) {
result.put("id", device.id().toString())
.put("available", service.isAvailable(device.id()))
.put("type", device.type().toString())
.put("role", service.getRole(device.id()).toString())
.put("mfr", device.manufacturer())
.put("hw", device.hwVersion())
.put("sw", device.swVersion())
.put("serial", device.serialNumber())
.set("annotations", annotations(mapper, device.annotations()));
result.add(jsonForEntity(device, Device.class));
}
return result;
}
......
......@@ -15,31 +15,28 @@
*/
package org.onosproject.cli.net;
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;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cli.Comparators;
import org.onosproject.core.CoreService;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowEntry.FlowEntryState;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.instructions.Instruction;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
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;
import static com.google.common.collect.Lists.newArrayList;
......@@ -73,7 +70,7 @@ public class FlowsListCommand extends AbstractShellCommand {
SortedMap<Device, List<FlowEntry>> flows = getSortedFlows(deviceService, service);
if (outputJson()) {
print("%s", json(coreService, flows.keySet(), flows));
print("%s", json(flows.keySet(), flows));
} else {
flows.forEach((device, flow) -> printFlows(device, flow, coreService));
}
......@@ -82,30 +79,27 @@ public class FlowsListCommand extends AbstractShellCommand {
/**
* Produces a JSON array of flows grouped by the each device.
*
* @param coreService core service
* @param devices collection of devices to group flow by
* @param flows collection of flows per each device
* @return JSON array
*/
private JsonNode json(CoreService coreService, Iterable<Device> devices,
private JsonNode json(Iterable<Device> devices,
Map<Device, List<FlowEntry>> flows) {
ObjectMapper mapper = new ObjectMapper();
ArrayNode result = mapper.createArrayNode();
for (Device device : devices) {
result.add(json(coreService, mapper, device, flows.get(device)));
result.add(json(mapper, device, flows.get(device)));
}
return result;
}
// Produces JSON object with the flows of the given device.
private ObjectNode json(CoreService coreService, ObjectMapper mapper,
private ObjectNode json(ObjectMapper mapper,
Device device, List<FlowEntry> flows) {
ObjectNode result = mapper.createObjectNode();
ArrayNode array = mapper.createArrayNode();
for (FlowEntry flow : flows) {
array.add(json(coreService, mapper, flow));
}
flows.forEach(flow -> array.add(jsonForEntity(flow, FlowEntry.class)));
result.put("device", device.id().toString())
.put("flowCount", flows.size())
......@@ -113,37 +107,6 @@ public class FlowsListCommand extends AbstractShellCommand {
return result;
}
// Produces JSON structure with the specified flow data.
private ObjectNode json(CoreService coreService, ObjectMapper mapper,
FlowEntry flow) {
ObjectNode result = mapper.createObjectNode();
ArrayNode crit = mapper.createArrayNode();
for (Criterion c : flow.selector().criteria()) {
crit.add(c.toString());
}
ArrayNode instr = mapper.createArrayNode();
for (Instruction i : flow.treatment().allInstructions()) {
instr.add(i.toString());
}
ApplicationId appCoreId = coreService.getAppId(flow.appId());
String appName = appCoreId == null ?
Short.toString(flow.appId())
: appCoreId.name();
result.put("flowId", Long.toHexString(flow.id().value()))
.put("state", flow.state().toString())
.put("bytes", flow.bytes())
.put("packets", flow.packets())
.put("life", flow.life())
.put("tableId", flow.tableId())
.put("appId", appName);
result.set("selector", crit);
result.set("treatment", instr);
return result;
}
/**
* Returns the list of devices sorted using the device ID URIs.
*
......
......@@ -15,19 +15,18 @@
*/
package org.onosproject.cli.net;
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;
import java.util.Collections;
import java.util.List;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cli.Comparators;
import org.onosproject.net.Host;
import org.onosproject.net.host.HostService;
import org.onlab.packet.IpAddress;
import java.util.Collections;
import java.util.List;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import static com.google.common.collect.Lists.newArrayList;
......@@ -54,30 +53,11 @@ public class HostsListCommand extends AbstractShellCommand {
}
// Produces JSON structure.
private static JsonNode json(Iterable<Host> hosts) {
private JsonNode json(Iterable<Host> hosts) {
ObjectMapper mapper = new ObjectMapper();
ArrayNode result = mapper.createArrayNode();
for (Host host : hosts) {
result.add(json(mapper, host));
}
return result;
}
// Produces JSON structure.
private static JsonNode json(ObjectMapper mapper, Host host) {
ObjectNode loc = LinksListCommand.json(mapper, host.location())
.put("time", host.location().time());
ArrayNode ips = mapper.createArrayNode();
for (IpAddress ip : host.ipAddresses()) {
ips.add(ip.toString());
}
ObjectNode result = mapper.createObjectNode()
.put("id", host.id().toString())
.put("mac", host.mac().toString())
.put("vlan", host.vlan().toString());
result.set("location", loc);
result.set("ips", ips);
result.set("annotations", annotations(mapper, host.annotations()));
hosts.forEach(host -> result.add(jsonForEntity(host, Host.class)));
return result;
}
......
......@@ -15,16 +15,11 @@
*/
package org.onosproject.cli.net;
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;
import java.util.List;
import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.commands.Option;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Link;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.intent.ConnectivityIntent;
import org.onosproject.net.intent.HostToHostIntent;
import org.onosproject.net.intent.Intent;
......@@ -36,8 +31,10 @@ import org.onosproject.net.intent.PathIntent;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.net.intent.SinglePointToMultiPointIntent;
import java.util.List;
import java.util.Set;
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;
/**
* Lists the inventory of intents and their states.
......@@ -393,81 +390,9 @@ public class IntentsListCommand extends AbstractShellCommand {
private JsonNode json(IntentService service, Iterable<Intent> intents) {
ObjectMapper mapper = new ObjectMapper();
ArrayNode result = mapper.createArrayNode();
for (Intent intent : intents) {
result.add(json(service, mapper, intent));
}
return result;
}
private JsonNode json(IntentService service, ObjectMapper mapper, Intent intent) {
ObjectNode result = mapper.createObjectNode()
.put("id", intent.id().toString())
.put("type", intent.getClass().getSimpleName())
.put("appId", intent.appId().name());
IntentState state = service.getIntentState(intent.key());
if (state != null) {
result.put("state", state.toString());
}
if (!intent.resources().isEmpty()) {
ArrayNode rnode = mapper.createArrayNode();
for (NetworkResource resource : intent.resources()) {
rnode.add(resource.toString());
}
result.set("resources", rnode);
}
if (intent instanceof ConnectivityIntent) {
ConnectivityIntent ci = (ConnectivityIntent) intent;
if (!ci.selector().criteria().isEmpty()) {
result.put("selector", ci.selector().criteria().toString());
}
if (!ci.treatment().allInstructions().isEmpty()) {
result.put("treatment", ci.treatment().allInstructions().toString());
}
}
if (intent instanceof PathIntent) {
PathIntent pi = (PathIntent) intent;
ArrayNode pnode = mapper.createArrayNode();
for (Link link : pi.path().links()) {
pnode.add(link.toString());
}
result.set("path", pnode);
} else if (intent instanceof HostToHostIntent) {
HostToHostIntent pi = (HostToHostIntent) intent;
result.set("host1", LinksListCommand.json(mapper, pi.one()));
result.set("host2", LinksListCommand.json(mapper, pi.two()));
} else if (intent instanceof PointToPointIntent) {
PointToPointIntent pi = (PointToPointIntent) intent;
result.set("ingress", LinksListCommand.json(mapper, pi.ingressPoint()));
result.set("egress", LinksListCommand.json(mapper, pi.egressPoint()));
} else if (intent instanceof MultiPointToSinglePointIntent) {
MultiPointToSinglePointIntent pi = (MultiPointToSinglePointIntent) intent;
result.set("ingress", json(mapper, pi.ingressPoints()));
result.set("egress", LinksListCommand.json(mapper, pi.egressPoint()));
} else if (intent instanceof SinglePointToMultiPointIntent) {
SinglePointToMultiPointIntent pi = (SinglePointToMultiPointIntent) intent;
result.set("ingress", LinksListCommand.json(mapper, pi.ingressPoint()));
result.set("egress", json(mapper, pi.egressPoints()));
} else if (intent instanceof LinkCollectionIntent) {
LinkCollectionIntent li = (LinkCollectionIntent) intent;
result.set("links", LinksListCommand.json(li.links()));
}
List<Intent> installable = service.getInstallableIntents(intent.key());
if (installable != null && !installable.isEmpty()) {
result.set("installable", json(service, installable));
}
intents.forEach(intent -> result.add(jsonForEntity(intent, Intent.class)));
return result;
}
private JsonNode json(ObjectMapper mapper, Set<ConnectPoint> connectPoints) {
ArrayNode result = mapper.createArrayNode();
for (ConnectPoint cp : connectPoints) {
result.add(LinksListCommand.json(mapper, cp));
}
return result;
}
}
......
......@@ -15,18 +15,17 @@
*/
package org.onosproject.cli.net;
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;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.HostId;
import org.onosproject.net.Link;
import org.onosproject.net.link.LinkService;
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;
import static org.onosproject.net.DeviceId.deviceId;
/**
......@@ -49,7 +48,7 @@ public class LinksListCommand extends AbstractShellCommand {
Iterable<Link> links = uri != null ?
service.getDeviceLinks(deviceId(uri)) : service.getLinks();
if (outputJson()) {
print("%s", json(links));
print("%s", json(this, links));
} else {
for (Link link : links) {
print(linkString(link));
......@@ -60,59 +59,28 @@ public class LinksListCommand extends AbstractShellCommand {
/**
* Produces a JSON array containing the specified links.
*
* @param context context to use for looking up codecs
* @param links collection of links
* @return JSON array
*/
public static JsonNode json(Iterable<Link> links) {
public static JsonNode json(AbstractShellCommand context, Iterable<Link> links) {
ObjectMapper mapper = new ObjectMapper();
ArrayNode result = mapper.createArrayNode();
for (Link link : links) {
result.add(json(mapper, link));
}
links.forEach(link -> result.add(context.jsonForEntity(link, Link.class)));
return result;
}
/**
* Produces a JSON object for the specified link.
*
* @param mapper object mapper
* @param context context to use for looking up codecs
* @param link link to encode
* @return JSON object
*/
public static ObjectNode json(ObjectMapper mapper, Link link) {
ObjectNode result = mapper.createObjectNode();
result.set("src", json(mapper, link.src()));
result.set("dst", json(mapper, link.dst()));
result.put("type", link.type().toString());
result.put("state", link.state().toString());
result.set("annotations", annotations(mapper, link.annotations()));
return result;
}
/**
* Produces a JSON object for the specified host ID.
*
* @param mapper object mapper
* @param hostId host ID to encode
* @return JSON object
*/
public static ObjectNode json(ObjectMapper mapper, HostId hostId) {
return mapper.createObjectNode()
.put("mac", hostId.mac().toString())
.put("vlanId", hostId.vlanId().toString());
}
/**
* Produces a JSON object for the specified connect point.
*
* @param mapper object mapper
* @param connectPoint connection point to encode
* @return JSON object
*/
public static ObjectNode json(ObjectMapper mapper, ConnectPoint connectPoint) {
return mapper.createObjectNode()
.put("device", connectPoint.deviceId().toString())
.put("port", connectPoint.port().toString());
public static ObjectNode json(AbstractShellCommand context, Link link) {
return context.jsonForEntity(link, Link.class);
}
/**
......
......@@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.net.Link;
import org.onosproject.net.Path;
......@@ -51,7 +52,7 @@ public class PathListCommand extends TopologyCommand {
init();
Set<Path> paths = service.getPaths(topology, deviceId(src), deviceId(dst));
if (outputJson()) {
print("%s", json(paths));
print("%s", json(this, paths));
} else {
for (Path path : paths) {
print(pathString(path));
......@@ -62,16 +63,17 @@ public class PathListCommand extends TopologyCommand {
/**
* Produces a JSON array containing the specified paths.
*
* @param context context to use for looking up codecs
* @param paths collection of paths
* @return JSON array
*/
public static JsonNode json(Iterable<Path> paths) {
public static JsonNode json(AbstractShellCommand context, Iterable<Path> paths) {
ObjectMapper mapper = new ObjectMapper();
ArrayNode result = mapper.createArrayNode();
for (Path path : paths) {
result.add(LinksListCommand.json(mapper, path)
.put("cost", path.cost())
.set("links", LinksListCommand.json(path.links())));
result.add(LinksListCommand.json(context, path)
.put("cost", path.cost())
.set("links", LinksListCommand.json(context, path.links())));
}
return result;
}
......
......@@ -27,8 +27,6 @@ import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyProvider;
import org.onosproject.net.topology.TopologyService;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Lists summary of the current topology.
*/
......@@ -64,14 +62,7 @@ public class TopologyCommand extends AbstractShellCommand {
} else if (outputJson()) {
print("%s",
new ObjectMapper()
.createObjectNode()
.put("time", topology.time())
.put("created", formatCreationTime(topology.creationTime()))
.put("uptime", formatElapsedTime(topologyUptime))
.put("deviceCount", topology.deviceCount())
.put("linkCount", topology.linkCount())
.put("clusterCount", topology.clusterCount()));
jsonForEntity(topology, Topology.class));
} else {
print(FMT, formatCreationTime(topology.creationTime()),
formatElapsedTime(topologyUptime),
......
......@@ -45,6 +45,6 @@ public interface CodecContext {
* @param <T> service type
* @return JSON codec; null if no codec available for the class
*/
<T> T get(Class<T> serviceClass);
<T> T getService(Class<T> serviceClass);
}
......
......@@ -60,4 +60,9 @@ public class AbstractWebResource extends BaseResource implements CodecContext {
return result;
}
@Override
public <T> T getService(Class<T> serviceClass) {
return get(serviceClass);
}
}
......
......@@ -92,7 +92,7 @@ public class JsonCodecTest {
}
@Override
public <T> T get(Class<T> serviceClass) {
public <T> T getService(Class<T> serviceClass) {
return null;
}
}
......
......@@ -31,7 +31,7 @@ public final class ApplicationCodec extends JsonCodec<Application> {
@Override
public ObjectNode encode(Application app, CodecContext context) {
checkNotNull(app, "Application cannot be null");
ApplicationService service = context.get(ApplicationService.class);
ApplicationService service = context.getService(ApplicationService.class);
ObjectNode result = context.mapper().createObjectNode()
.put("name", app.id().name())
.put("id", app.id().id())
......
......@@ -35,7 +35,7 @@ public final class ControllerNodeCodec extends JsonCodec<ControllerNode> {
@Override
public ObjectNode encode(ControllerNode node, CodecContext context) {
checkNotNull(node, "Controller node cannot be null");
ClusterService service = context.get(ClusterService.class);
ClusterService service = context.getService(ClusterService.class);
return context.mapper().createObjectNode()
.put("id", node.id().toString())
.put("ip", node.ip().toString())
......
......@@ -48,7 +48,7 @@ public final class DeviceCodec extends AnnotatedCodec<Device> {
@Override
public ObjectNode encode(Device device, CodecContext context) {
checkNotNull(device, "Device cannot be null");
DeviceService service = context.get(DeviceService.class);
DeviceService service = context.getService(DeviceService.class);
ObjectNode result = context.mapper().createObjectNode()
.put(ID, device.id().toString())
.put(TYPE, device.type().name())
......
......@@ -37,6 +37,7 @@ public final class LinkCodec extends AnnotatedCodec<Link> {
private static final String SRC = "src";
private static final String DST = "dst";
private static final String TYPE = "type";
private static final String STATE = "state";
@Override
public ObjectNode encode(Link link, CodecContext context) {
......@@ -46,6 +47,9 @@ public final class LinkCodec extends AnnotatedCodec<Link> {
result.set(SRC, codec.encode(link.src(), context));
result.set(DST, codec.encode(link.dst(), context));
result.put(TYPE, link.type().toString());
if (link.state() != null) {
result.put(STATE, link.state().toString());
}
return annotate(result, link, context);
}
......
......@@ -52,7 +52,7 @@ public class MockCodecContext implements CodecContext {
@SuppressWarnings("unchecked")
@Override
public <T> T get(Class<T> serviceClass) {
public <T> T getService(Class<T> serviceClass) {
return (T) services.get(serviceClass);
}
......
......@@ -67,7 +67,7 @@ public class ApplicationsResourceTest extends ResourceTest {
@Override
@SuppressWarnings("unchecked")
public <T> T get(Class<T> serviceClass) {
public <T> T getService(Class<T> serviceClass) {
return (T) service;
}
}
......