Initial import of CFM and SOAM api
Change-Id: Icf5cc2d5fb34b75460e80e8cced0d70265bcd33b
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatCodec.java
new file mode 100644
index 0000000..7bd0d7a
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatCodec.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.time.Duration;
+import java.util.Map;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStat;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Encode and decode to/from JSON to DelayMeasurementStat object.
+ */
+public class DelayMeasurementStatCodec extends JsonCodec<DelayMeasurementStat> {
+
+ private static final String LOWER_LIMIT = "lowerLimit";
+ private static final String COUNT = "count";
+ private static final String BINS = "bins";
+ private static final String SOAM_PDUS_SENT = "soamPdusSent";
+ private static final String SOAM_PDUS_RECEIVED = "soamPdusReceived";
+
+ @Override
+ public ObjectNode encode(DelayMeasurementStat dmStat, CodecContext context) {
+ checkNotNull(dmStat, "DM stat cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put("elapsedTime", dmStat.elapsedTime().toString())
+ .put("suspectStatus", String.valueOf(dmStat.suspectStatus()));
+
+ if (dmStat.frameDelayTwoWayMin() != null) {
+ result = result.put("frameDelayTwoWayMin",
+ dmStat.frameDelayTwoWayMin().toString());
+ }
+ if (dmStat.frameDelayTwoWayMax() != null) {
+ result = result.put("frameDelayTwoWayMax",
+ dmStat.frameDelayTwoWayMax().toString());
+ }
+ if (dmStat.frameDelayTwoWayAvg() != null) {
+ result = result.put("frameDelayTwoWayAvg",
+ dmStat.frameDelayTwoWayAvg().toString());
+ }
+ if (dmStat.frameDelayTwoWayBins() != null) {
+ result = (ObjectNode) result.set("frameDelayTwoWayBins",
+ encode(dmStat.frameDelayTwoWayBins(), context));
+ }
+ if (dmStat.frameDelayForwardMin() != null) {
+ result = result.put("frameDelayForwardMin",
+ dmStat.frameDelayForwardMin().toString());
+ }
+ if (dmStat.frameDelayForwardMax() != null) {
+ result = result.put("frameDelayForwardMax",
+ dmStat.frameDelayForwardMax().toString());
+ }
+ if (dmStat.frameDelayForwardAvg() != null) {
+ result = result.put("frameDelayForwardAvg",
+ dmStat.frameDelayForwardAvg().toString());
+ }
+ if (dmStat.frameDelayForwardBins() != null) {
+ result = (ObjectNode) result.set("frameDelayForwardBins",
+ encode(dmStat.frameDelayForwardBins(), context));
+ }
+ if (dmStat.frameDelayBackwardMin() != null) {
+ result = result.put("frameDelayBackwardMin",
+ dmStat.frameDelayBackwardMin().toString());
+ }
+ if (dmStat.frameDelayBackwardMax() != null) {
+ result = result.put("frameDelayBackwardMax",
+ dmStat.frameDelayBackwardMax().toString());
+ }
+ if (dmStat.frameDelayBackwardAvg() != null) {
+ result = result.put("frameDelayBackwardAvg",
+ dmStat.frameDelayBackwardAvg().toString());
+ }
+ if (dmStat.frameDelayBackwardBins() != null) {
+ result = (ObjectNode) result.set("frameDelayBackwardBins",
+ encode(dmStat.frameDelayBackwardBins(), context));
+ }
+ if (dmStat.interFrameDelayVariationTwoWayMin() != null) {
+ result = result.put("interFrameDelayVariationTwoWayMin",
+ dmStat.interFrameDelayVariationTwoWayMin().toString());
+ }
+ if (dmStat.interFrameDelayVariationTwoWayMax() != null) {
+ result.put("interFrameDelayVariationTwoWayMax",
+ dmStat.interFrameDelayVariationTwoWayMax().toString());
+ }
+ if (dmStat.interFrameDelayVariationTwoWayAvg() != null) {
+ result.put("interFrameDelayVariationTwoWayAvg",
+ dmStat.interFrameDelayVariationTwoWayAvg().toString());
+ }
+ if (dmStat.interFrameDelayVariationTwoWayBins() != null) {
+ result = (ObjectNode) result.set("interFrameDelayVariationTwoWayBins",
+ encode(dmStat.interFrameDelayVariationTwoWayBins(), context));
+ }
+ if (dmStat.interFrameDelayVariationForwardMin() != null) {
+ result = result.put("interFrameDelayVariationForwardMin",
+ dmStat.interFrameDelayVariationForwardMin().toString());
+ }
+ if (dmStat.interFrameDelayVariationForwardMax() != null) {
+ result = result.put("interFrameDelayVariationForwardMax",
+ dmStat.interFrameDelayVariationForwardMax().toString());
+ }
+ if (dmStat.interFrameDelayVariationForwardAvg() != null) {
+ result = result.put("interFrameDelayVariationForwardAvg",
+ dmStat.interFrameDelayVariationForwardAvg().toString());
+ }
+ if (dmStat.interFrameDelayVariationForwardBins() != null) {
+ result = (ObjectNode) result.set("interFrameDelayVariationForwardBins",
+ encode(dmStat.interFrameDelayVariationForwardBins(), context));
+ }
+ if (dmStat.interFrameDelayVariationBackwardMin() != null) {
+ result = result.put("interFrameDelayVariationBackwardMin",
+ dmStat.interFrameDelayVariationBackwardMin().toString());
+ }
+ if (dmStat.interFrameDelayVariationBackwardMax() != null) {
+ result = result.put("interFrameDelayVariationBackwardMax",
+ dmStat.interFrameDelayVariationBackwardMax().toString());
+ }
+ if (dmStat.interFrameDelayVariationBackwardAvg() != null) {
+ result = result.put("interFrameDelayVariationBackwardAvg",
+ dmStat.interFrameDelayVariationBackwardAvg().toString());
+ }
+ if (dmStat.interFrameDelayVariationBackwardBins() != null) {
+ result = (ObjectNode) result.set("interFrameDelayVariationBackwardBins",
+ encode(dmStat.interFrameDelayVariationBackwardBins(), context));
+ }
+ if (dmStat.frameDelayRangeTwoWayMax() != null) {
+ result = result.put("frameDelayRangeTwoWayMax",
+ dmStat.frameDelayRangeTwoWayMax().toString());
+ }
+ if (dmStat.frameDelayRangeTwoWayAvg() != null) {
+ result = result.put("frameDelayRangeTwoWayAvg",
+ dmStat.frameDelayRangeTwoWayAvg().toString());
+ }
+ if (dmStat.frameDelayRangeTwoWayBins() != null) {
+ result = (ObjectNode) result.set("frameDelayRangeTwoWayBins",
+ encode(dmStat.frameDelayRangeTwoWayBins(), context));
+ }
+ if (dmStat.frameDelayRangeForwardMax() != null) {
+ result = result.put("frameDelayRangeForwardMax",
+ dmStat.frameDelayRangeForwardMax().toString());
+ }
+ if (dmStat.frameDelayRangeForwardAvg() != null) {
+ result = result.put("frameDelayRangeForwardAvg",
+ dmStat.frameDelayRangeForwardAvg().toString());
+ }
+ if (dmStat.frameDelayRangeForwardBins() != null) {
+ result = (ObjectNode) result.set("frameDelayRangeForwardBins",
+ encode(dmStat.frameDelayRangeForwardBins(), context));
+ }
+ if (dmStat.frameDelayRangeBackwardMax() != null) {
+ result = result.put("frameDelayRangeBackwardMax",
+ dmStat.frameDelayRangeBackwardMax().toString());
+ }
+ if (dmStat.frameDelayRangeBackwardAvg() != null) {
+ result = result.put("frameDelayRangeBackwardAvg",
+ dmStat.frameDelayRangeBackwardAvg().toString());
+ }
+ if (dmStat.frameDelayRangeBackwardBins() != null) {
+ result = (ObjectNode) result.set("frameDelayRangeBackwardBins",
+ encode(dmStat.frameDelayRangeBackwardBins(), context));
+ }
+
+ if (dmStat.soamPdusReceived() != null) {
+ result = result.put(SOAM_PDUS_RECEIVED, dmStat.soamPdusReceived().toString());
+ }
+
+ if (dmStat.soamPdusSent() != null) {
+ result = result.put(SOAM_PDUS_SENT, dmStat.soamPdusSent().toString());
+ }
+
+ return result;
+ }
+
+ private ObjectNode encode(Map<Duration, Integer> bins, CodecContext context) {
+ checkNotNull(bins, "Bins cannot be null");
+ ArrayNode binsResult = context.mapper().createArrayNode();
+ bins.keySet().forEach(lwrLimit -> binsResult.add(encode(lwrLimit, bins.get(lwrLimit), context)));
+
+ return (ObjectNode) context.mapper().createObjectNode().set(BINS, binsResult);
+ }
+
+ private ObjectNode encode(Duration duration, Integer count, CodecContext context) {
+ return context.mapper().createObjectNode()
+ .put(LOWER_LIMIT, duration.toString())
+ .put(COUNT, count);
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatCurrentCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatCurrentCodec.java
new file mode 100644
index 0000000..a79cd90
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatCurrentCodec.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Encode and decode to/from JSON to DelayMeasurementStatCurrent object.
+ */
+public class DelayMeasurementStatCurrentCodec extends JsonCodec<DelayMeasurementStatCurrent> {
+
+ @Override
+ public ObjectNode encode(DelayMeasurementStatCurrent dmCurrent, CodecContext context) {
+ checkNotNull(dmCurrent, "DM current cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put("startTime", dmCurrent.startTime().toString())
+ .put("elapsedTime", dmCurrent.elapsedTime().toString());
+
+ ObjectNode resultAbstract = new DelayMeasurementStatCodec().encode(dmCurrent, context);
+ result.setAll(resultAbstract);
+
+ return result;
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatHistoryCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatHistoryCodec.java
new file mode 100644
index 0000000..8901958
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatHistoryCodec.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Encode and decode to/from JSON to DelayMeasurementStatHistory object.
+ */
+public class DelayMeasurementStatHistoryCodec extends JsonCodec<DelayMeasurementStatHistory> {
+
+ @Override
+ public ObjectNode encode(DelayMeasurementStatHistory dmHistory, CodecContext context) {
+ checkNotNull(dmHistory, "DM history cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put("historyId", String.valueOf(dmHistory.historyStatsId()))
+ .put("endTime", dmHistory.endTime().toString());
+ ObjectNode resultAbstract = new DelayMeasurementStatCodec().encode(dmHistory, context);
+ result.setAll(resultAbstract);
+ return result;
+ }
+
+ @Override
+ public ArrayNode encode(Iterable<DelayMeasurementStatHistory> historyEntities, CodecContext context) {
+ ArrayNode an = context.mapper().createArrayNode();
+ historyEntities.forEach(history -> an.add(encode(history, context)));
+ return an;
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/DmCreateCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/DmCreateCodec.java
new file mode 100644
index 0000000..8743eb4
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/DmCreateCodec.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+import java.time.Duration;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException;
+import org.onosproject.incubator.net.l2monitoring.soam.StartTime;
+import org.onosproject.incubator.net.l2monitoring.soam.StopTime;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementCreate;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmCreateBuilder;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmType;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Encode and decode to/from JSON to DelayMeasurementCreate object.
+ */
+public class DmCreateCodec extends JsonCodec<DelayMeasurementCreate> {
+
+ private static final String VERSION = "version";
+ private static final String DM = "dm";
+ private static final String DM_CFG_TYPE = "dmCfgType";
+ private static final String DMDMM = "DMDMM";
+ private static final String REMOTE_MEP_ID = "remoteMepId";
+ private static final String PRIORITY = "priority";
+ private static final String MEASUREMENTS_ENABLED = "measurementsEnabled";
+ private static final String BINS_PER_FD_INTERVAL = "binsPerFdInterval";
+ private static final String BINS_PER_IFDV_INTERVAL = "binsPerIfdvInterval";
+ private static final String IFDV_SELECTION_OFFSET = "ifdvSelectionOffset";
+ private static final String BINS_PER_FDR_INTERVAL = "binsPerFdrInterval";
+ private static final String FRAME_SIZE = "frameSize";
+ private static final String MESSAGE_PERIOD_MS = "messagePeriodMs";
+ private static final String MEASUREMENT_INTERVAL_MINS = "measurementIntervalMins";
+ private static final String ALIGN_MEASUREMENT_INTERVALS = "alignMeasurementIntervals";
+ private static final String ALIGN_MEASUREMENT_OFFSET_MINS = "alignMeasurementOffsetMins";
+ private static final String START_TIME = "startTime";
+ private static final String STOP_TIME = "stopTime";
+
+ @Override
+ public DelayMeasurementCreate decode(ObjectNode json,
+ CodecContext context) {
+
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ JsonNode dmNode = json.get(DM);
+ Version version = Version.Y17312011;
+ if (dmNode.get(VERSION) != null) {
+ version = Version.valueOf(dmNode.get(VERSION).asText());
+ }
+ DmType dmCfgType = DmType.DMDMM;
+ if (dmNode.get(DM_CFG_TYPE) != null) {
+ dmCfgType = DmType.valueOf(dmNode.get(DM_CFG_TYPE).asText(DMDMM));
+ }
+ MepId remoteMepId = MepId.valueOf(
+ nullIsIllegal(dmNode.get(REMOTE_MEP_ID), REMOTE_MEP_ID + " is required")
+ .shortValue());
+ Priority prio = Priority.valueOf(nullIsIllegal(dmNode.get(PRIORITY),
+ PRIORITY + " is required in the format 'PRIOn'").asText());
+
+ try {
+ DmCreateBuilder builder = DefaultDelayMeasurementCreate
+ .builder(dmCfgType, version, remoteMepId, prio);
+
+ if (dmNode.get(MEASUREMENTS_ENABLED) != null) {
+ context.codec(MeasurementOption.class)
+ .decode((ArrayNode) (dmNode.get(MEASUREMENTS_ENABLED)), context)
+ .forEach(builder::addToMeasurementsEnabled);
+ }
+
+ if (dmNode.get(BINS_PER_FD_INTERVAL) != null) {
+ builder = builder.binsPerFdInterval(
+ (short) dmNode.get(BINS_PER_FD_INTERVAL).asInt());
+ }
+ if (dmNode.get(BINS_PER_IFDV_INTERVAL) != null) {
+ builder = builder.binsPerIfdvInterval(
+ (short) dmNode.get(BINS_PER_IFDV_INTERVAL).asInt());
+ }
+ if (dmNode.get(IFDV_SELECTION_OFFSET) != null) {
+ builder = builder.ifdvSelectionOffset(
+ (short) dmNode.get(IFDV_SELECTION_OFFSET).asInt());
+ }
+ if (dmNode.get(BINS_PER_FDR_INTERVAL) != null) {
+ builder = builder.binsPerFdrInterval(
+ (short) dmNode.get(BINS_PER_FDR_INTERVAL).asInt());
+ }
+ if (dmNode.get(FRAME_SIZE) != null) {
+ builder = (DmCreateBuilder) builder.frameSize(
+ (short) dmNode.get(FRAME_SIZE).asInt());
+ }
+ if (dmNode.get(MESSAGE_PERIOD_MS) != null) {
+ builder = (DmCreateBuilder) builder.messagePeriod(Duration.ofMillis(
+ dmNode.get(MESSAGE_PERIOD_MS).asInt()));
+ }
+ if (dmNode.get(MEASUREMENT_INTERVAL_MINS) != null) {
+ builder = (DmCreateBuilder) builder.measurementInterval(
+ Duration.ofMinutes(
+ dmNode.get(MEASUREMENT_INTERVAL_MINS).asInt()));
+ }
+ if (dmNode.get(ALIGN_MEASUREMENT_INTERVALS) != null) {
+ builder = (DmCreateBuilder) builder.alignMeasurementIntervals(
+ dmNode.get(ALIGN_MEASUREMENT_INTERVALS).asBoolean());
+ }
+ if (dmNode.get(ALIGN_MEASUREMENT_OFFSET_MINS) != null) {
+ builder = (DmCreateBuilder) builder.alignMeasurementOffset(Duration.ofMinutes(
+ dmNode.get(ALIGN_MEASUREMENT_OFFSET_MINS).asInt()));
+ }
+ if (dmNode.get(START_TIME) != null) {
+ builder = (DmCreateBuilder) builder.startTime(context.codec(StartTime.class)
+ .decode((ObjectNode) dmNode.get(START_TIME), context));
+ }
+ if (dmNode.get(STOP_TIME) != null) {
+ builder = (DmCreateBuilder) builder.stopTime(context.codec(StopTime.class)
+ .decode((ObjectNode) dmNode.get(STOP_TIME), context));
+ }
+
+ return builder.build();
+ } catch (SoamConfigException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ @Override
+ public ObjectNode encode(DelayMeasurementCreate dm, CodecContext context) {
+ checkNotNull(dm, "DM cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(DM_CFG_TYPE, dm.dmCfgType().name())
+ .put(VERSION, dm.version().name())
+ .put(REMOTE_MEP_ID, dm.remoteMepId().id())
+ .put(PRIORITY, dm.priority().name());
+
+ if (dm.measurementsEnabled() != null) {
+ result.set(MEASUREMENTS_ENABLED, new DmMeasurementOptionCodec()
+ .encode(dm.measurementsEnabled(), context));
+ }
+
+ if (dm.messagePeriod() != null) {
+ result.put(MESSAGE_PERIOD_MS, dm.messagePeriod().toMillis());
+ }
+ if (dm.frameSize() != null) {
+ result.put(FRAME_SIZE, dm.frameSize());
+ }
+
+
+ return result;
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/DmEntryCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/DmEntryCodec.java
new file mode 100644
index 0000000..ce851d6
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/DmEntryCodec.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Iterator;
+import java.util.Map.Entry;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Encode and decode to/from JSON to DelayMeasurementEntry object.
+ */
+public class DmEntryCodec extends JsonCodec<DelayMeasurementEntry> {
+
+ private static final String DM_ID = "dmId";
+ private static final String SESSION_STATUS = "sessionStatus";
+ private static final String FRAME_DELAY_TWO_WAY = "frameDelayTwoWay";
+ private static final String FRAME_DELAY_FORWARD = "frameDelayForward";
+ private static final String FRAME_DELAY_BACKWARD = "frameDelayBackward";
+ private static final String INTER_FRAME_DELAY_VARIATION_TWO_WAY = "interFrameDelayVariationTwoWay";
+ private static final String INTER_FRAME_DELAY_VARIATION_FORWARD = "interFrameDelayVariationForward";
+ private static final String INTER_FRAME_DELAY_VARIATION_BACKWARD = "interFrameDelayVariationBackward";
+ private static final String CURRENT = "current";
+ private static final String HISTORIC = "historic";
+
+ @Override
+ public ObjectNode encode(DelayMeasurementEntry dm, CodecContext context) {
+ checkNotNull(dm, "DM cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(DM_ID, dm.dmId().toString());
+
+ if (dm.sessionStatus() != null) {
+ result.put(SESSION_STATUS, dm.sessionStatus().name());
+ }
+ if (dm.frameDelayTwoWay() != null) {
+ result.put(FRAME_DELAY_TWO_WAY, dm.frameDelayTwoWay().toString());
+ }
+ if (dm.frameDelayForward() != null) {
+ result.put(FRAME_DELAY_FORWARD, dm.frameDelayForward().toString());
+ }
+ if (dm.frameDelayBackward() != null) {
+ result.put(FRAME_DELAY_BACKWARD, dm.frameDelayBackward().toString());
+ }
+ if (dm.interFrameDelayVariationTwoWay() != null) {
+ result.put(INTER_FRAME_DELAY_VARIATION_TWO_WAY,
+ dm.interFrameDelayVariationTwoWay().toString());
+ }
+ if (dm.interFrameDelayVariationForward() != null) {
+ result.put(INTER_FRAME_DELAY_VARIATION_FORWARD,
+ dm.interFrameDelayVariationForward().toString());
+ }
+ if (dm.interFrameDelayVariationBackward() != null) {
+ result.put(INTER_FRAME_DELAY_VARIATION_BACKWARD,
+ dm.interFrameDelayVariationBackward().toString());
+ }
+
+ ObjectNode dmAttrs = new DmCreateCodec().encode(dm, context);
+ Iterator<Entry<String, JsonNode>> elements = dmAttrs.fields();
+ while (elements.hasNext()) {
+ Entry<String, JsonNode> element = elements.next();
+ result.set(element.getKey(), element.getValue());
+ }
+
+ if (dm.currentResult() != null) {
+ result.set(CURRENT, new DelayMeasurementStatCurrentCodec()
+ .encode(dm.currentResult(), context));
+ }
+
+ if (dm.historicalResults() != null) {
+ result.set(HISTORIC, new DelayMeasurementStatHistoryCodec()
+ .encode(dm.historicalResults(), context));
+ }
+
+ return result;
+ }
+
+ @Override
+ public ArrayNode encode(Iterable<DelayMeasurementEntry> dmEntities, CodecContext context) {
+ ArrayNode an = context.mapper().createArrayNode();
+ dmEntities.forEach(dm -> an.add(encode(dm, context)));
+ return an;
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/DmMeasurementOptionCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/DmMeasurementOptionCodec.java
new file mode 100644
index 0000000..8c8a5a0
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/DmMeasurementOptionCodec.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+/**
+ * Encode and decode to/from JSON to MeasurementOption object.
+ */
+public class DmMeasurementOptionCodec extends JsonCodec<MeasurementOption> {
+
+ @Override
+ public ArrayNode encode(Iterable<MeasurementOption> entities,
+ CodecContext context) {
+ ArrayNode an = context.mapper().createArrayNode();
+ entities.forEach(node -> an.add(node.name()));
+
+ return an;
+ }
+
+ @Override
+ public List<MeasurementOption> decode(ArrayNode json,
+ CodecContext context) {
+ if (json == null) {
+ return null;
+ }
+ List<MeasurementOption> moList = new ArrayList<>();
+ json.forEach(node -> moList.add(MeasurementOption.valueOf(node.asText())));
+ return moList;
+ }
+
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LmCounterOptionCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LmCounterOptionCodec.java
new file mode 100644
index 0000000..9e3e40e
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LmCounterOptionCodec.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate.CounterOption;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Encode and decode to/from JSON to CounterOption object.
+ */
+public class LmCounterOptionCodec extends JsonCodec<CounterOption> {
+
+ @Override
+ public ArrayNode encode(Iterable<CounterOption> entities,
+ CodecContext context) {
+ ArrayNode an = context.mapper().createArrayNode();
+ entities.forEach(node -> an.add(node.name()));
+
+ return an;
+ }
+
+ @Override
+ public List<CounterOption> decode(ArrayNode json,
+ CodecContext context) {
+ if (json == null) {
+ return null;
+ }
+ List<CounterOption> moList = new ArrayList<>();
+ json.forEach(node -> moList.add(CounterOption.valueOf(node.asText())));
+ return moList;
+ }
+
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LmCreateCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LmCreateCodec.java
new file mode 100644
index 0000000..e88fb2f
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LmCreateCodec.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.soam.MilliPct;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException;
+import org.onosproject.incubator.net.l2monitoring.soam.StartTime;
+import org.onosproject.incubator.net.l2monitoring.soam.StopTime;
+import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.DefaultLmCreate;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementThreshold;
+
+import java.time.Duration;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+import static org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate.CounterOption;
+import static org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate.LmType;
+import static org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate.LmCreateBuilder;
+
+/**
+ * Encode and decode to/from JSON to LossMeasurementCreate object.
+ */
+public class LmCreateCodec extends JsonCodec<LossMeasurementCreate> {
+
+ public static final String LM = "lm";
+ public static final String VERSION = "version";
+ public static final String LM_CFG_TYPE = "lmCfgType";
+ public static final String LMLMM = "LMLMM";
+ public static final String REMOTE_MEP_ID = "remoteMepId";
+ public static final String PRIORITY = "priority";
+ public static final String COUNTERS_ENABLED = "countersEnabled";
+ public static final String THRESHOLDS = "thresholds";
+ public static final String AVAILABILITY_MEASUREMENT_INTERVAL_MINS =
+ "availabilityMeasurementIntervalMins";
+ public static final String AVAILABILITY_NUMBER_CONSECUTIVE_FLR_MEASUREMENTS =
+ "availabilityNumberConsecutiveFlrMeasurements";
+ public static final String AVAILABILITY_FLR_THRESHOLD_PCT =
+ "availabilityFlrThresholdPct";
+ public static final String AVAILABILITY_NUMBER_CONSECUTIVE_INTERVALS =
+ "availabilityNumberConsecutiveIntervals";
+ public static final String AVAILABILITY_NUMBER_CONSECUTIVE_HIGH_FLR =
+ "availabilityNumberConsecutiveHighFlr";
+ public static final String FRAME_SIZE = "frameSize";
+ public static final String MESSAGE_PERIOD_MS = "messagePeriodMs";
+ public static final String MEASUREMENT_INTERVAL_MINS =
+ "measurementIntervalMins";
+ public static final String ALIGN_MEASUREMENT_INTERVALS =
+ "alignMeasurementIntervals";
+ public static final String ALIGN_MEASUREMENT_OFFSET_MINS =
+ "alignMeasurementOffsetMins";
+ public static final String START_TIME = "startTime";
+ public static final String STOP_TIME = "stopTime";
+
+ @Override
+ public LossMeasurementCreate decode(ObjectNode json,
+ CodecContext context) {
+
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ JsonNode lmNode = json.get(LM);
+ Version version = Version.Y17312011;
+ if (lmNode.get(VERSION) != null) {
+ version = Version.valueOf(lmNode.get(VERSION).asText());
+ }
+ LmType lmCfgType = LmType.LMLMM;
+ if (lmNode.get(LM_CFG_TYPE) != null) {
+ lmCfgType = LmType.valueOf(lmNode.get(LM_CFG_TYPE).asText(LMLMM));
+ }
+ MepId remoteMepId = MepId.valueOf(
+ nullIsIllegal(lmNode.get(REMOTE_MEP_ID), REMOTE_MEP_ID + " is required")
+ .shortValue());
+ Priority prio = Priority.valueOf(nullIsIllegal(lmNode.get(PRIORITY),
+ PRIORITY + " is required in the format 'PRIOn'").asText());
+
+ try {
+ LmCreateBuilder builder = DefaultLmCreate
+ .builder(version, remoteMepId, prio, lmCfgType);
+
+ if (lmNode.get(COUNTERS_ENABLED) != null) {
+ context.codec(CounterOption.class)
+ .decode((ArrayNode) (lmNode.get(COUNTERS_ENABLED)), context)
+ .forEach(builder::addToCountersEnabled);
+ }
+
+ if (lmNode.get(THRESHOLDS) != null) {
+ context.codec(LossMeasurementThreshold.class)
+ .decode((ArrayNode) (lmNode.get(THRESHOLDS)), context)
+ .forEach(builder::addToLossMeasurementThreshold);
+ }
+
+ if (lmNode.get(AVAILABILITY_MEASUREMENT_INTERVAL_MINS) != null) {
+ builder = builder.availabilityMeasurementInterval(
+ Duration.ofMinutes(lmNode.get(AVAILABILITY_MEASUREMENT_INTERVAL_MINS).asInt()));
+ }
+ if (lmNode.get(AVAILABILITY_NUMBER_CONSECUTIVE_FLR_MEASUREMENTS) != null) {
+ builder = builder.availabilityNumberConsecutiveFlrMeasurements(
+ lmNode.get(AVAILABILITY_NUMBER_CONSECUTIVE_FLR_MEASUREMENTS).asInt());
+ }
+ if (lmNode.get(AVAILABILITY_FLR_THRESHOLD_PCT) != null) {
+ builder = builder.availabilityFlrThreshold(
+ MilliPct.ofPercent((float) lmNode.get(AVAILABILITY_FLR_THRESHOLD_PCT).asDouble()));
+ }
+ if (lmNode.get(AVAILABILITY_NUMBER_CONSECUTIVE_INTERVALS) != null) {
+ builder = builder.availabilityNumberConsecutiveIntervals(
+ (short) lmNode.get(AVAILABILITY_NUMBER_CONSECUTIVE_INTERVALS).asInt());
+ }
+ if (lmNode.get(AVAILABILITY_NUMBER_CONSECUTIVE_HIGH_FLR) != null) {
+ builder = builder.availabilityNumberConsecutiveHighFlr(
+ (short) lmNode.get(AVAILABILITY_NUMBER_CONSECUTIVE_HIGH_FLR).asInt());
+ }
+ if (lmNode.get(FRAME_SIZE) != null) {
+ builder = (LmCreateBuilder) builder.frameSize(
+ (short) lmNode.get(FRAME_SIZE).asInt());
+ }
+ if (lmNode.get(MESSAGE_PERIOD_MS) != null) {
+ builder = (LmCreateBuilder) builder.messagePeriod(Duration.ofMillis(
+ lmNode.get(MESSAGE_PERIOD_MS).asInt()));
+ }
+ if (lmNode.get(MEASUREMENT_INTERVAL_MINS) != null) {
+ builder = (LmCreateBuilder) builder.measurementInterval(
+ Duration.ofMinutes(
+ lmNode.get(MEASUREMENT_INTERVAL_MINS).asInt()));
+ }
+ if (lmNode.get(ALIGN_MEASUREMENT_INTERVALS) != null) {
+ builder = (LmCreateBuilder) builder.alignMeasurementIntervals(
+ lmNode.get(ALIGN_MEASUREMENT_INTERVALS).asBoolean());
+ }
+ if (lmNode.get(ALIGN_MEASUREMENT_OFFSET_MINS) != null) {
+ builder = (LmCreateBuilder) builder.alignMeasurementOffset(Duration.ofMinutes(
+ lmNode.get(ALIGN_MEASUREMENT_OFFSET_MINS).asInt()));
+ }
+ if (lmNode.get(START_TIME) != null) {
+ builder = (LmCreateBuilder) builder.startTime(context.codec(StartTime.class)
+ .decode((ObjectNode) lmNode.get(START_TIME), context));
+ }
+ if (lmNode.get(STOP_TIME) != null) {
+ builder = (LmCreateBuilder) builder.stopTime(context.codec(StopTime.class)
+ .decode((ObjectNode) lmNode.get(STOP_TIME), context));
+ }
+
+
+ return builder.build();
+ } catch (SoamConfigException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ @Override
+ public ObjectNode encode(LossMeasurementCreate lm, CodecContext context) {
+ checkNotNull(lm, "LM cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(LM_CFG_TYPE, lm.lmCfgType().name())
+ .put(VERSION, lm.version().name())
+ .put(REMOTE_MEP_ID, lm.remoteMepId().id())
+ .put(PRIORITY, lm.priority().name());
+
+ if (lm.countersEnabled() != null) {
+ result.set(COUNTERS_ENABLED, new LmCounterOptionCodec()
+ .encode(lm.countersEnabled(), context));
+ }
+
+ if (lm.messagePeriod() != null) {
+ result.put(MESSAGE_PERIOD_MS, lm.messagePeriod().toMillis());
+ }
+ if (lm.frameSize() != null) {
+ result.put(FRAME_SIZE, lm.frameSize());
+ }
+
+
+ return result;
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LmEntryCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LmEntryCodec.java
new file mode 100644
index 0000000..251bcd9
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LmEntryCodec.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry;
+
+import java.util.Iterator;
+import java.util.Map.Entry;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Encode and decode to/from JSON to LossMeasurementEntry object.
+ */
+public class LmEntryCodec extends JsonCodec<LossMeasurementEntry> {
+
+ @Override
+ public ObjectNode encode(LossMeasurementEntry lm, CodecContext context) {
+ checkNotNull(lm, "LM cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put("lmId", lm.lmId().toString());
+
+ if (lm.measuredForwardFlr() != null) {
+ result.put("measuredForwardFlr", lm.measuredForwardFlr().percentValue());
+ }
+ if (lm.measuredBackwardFlr() != null) {
+ result.put("measuredBackwardFlr", lm.measuredBackwardFlr().percentValue());
+ }
+ if (lm.measuredAvailabilityForwardStatus() != null) {
+ result.put("measuredAvailabilityForwardStatus",
+ lm.measuredAvailabilityForwardStatus().name());
+ }
+ if (lm.measuredAvailabilityBackwardStatus() != null) {
+ result.put("measuredAvailabilityBackwardStatus",
+ lm.measuredAvailabilityBackwardStatus().name());
+ }
+ if (lm.measuredForwardLastTransitionTime() != null) {
+ result.put("measuredForwardLastTransitionTime",
+ lm.measuredForwardLastTransitionTime().toString());
+ }
+ if (lm.measuredBackwardLastTransitionTime() != null) {
+ result.put("measuredBackwardLastTransitionTime",
+ lm.measuredBackwardLastTransitionTime().toString());
+ }
+
+ ObjectNode lmAttrs = new LmCreateCodec().encode(lm, context);
+ Iterator<Entry<String, JsonNode>> elements = lmAttrs.fields();
+ while (elements.hasNext()) {
+ Entry<String, JsonNode> element = elements.next();
+ result.set(element.getKey(), element.getValue());
+ }
+
+ if (lm.measurementCurrent() != null) {
+ result.set("measurementCurrent", new LossMeasurementStatCurrentCodec()
+ .encode(lm.measurementCurrent(), context));
+ }
+
+ if (lm.measurementHistories() != null) {
+ result.set("measurementHistories", new LossMeasurementStatHistoryCodec()
+ .encode(lm.measurementHistories(), context));
+ }
+
+ if (lm.availabilityCurrent() != null) {
+ result.set("availabilityCurrent", new LossAvailabilityStatCurrentCodec()
+ .encode(lm.availabilityCurrent(), context));
+ }
+
+ if (lm.availabilityHistories() != null) {
+ result.set("availabilityHistories", new LossAvailabilityStatHistoryCodec()
+ .encode(lm.availabilityHistories(), context));
+ }
+
+ return result;
+ }
+
+ @Override
+ public ArrayNode encode(Iterable<LossMeasurementEntry> lmEntities, CodecContext context) {
+ ArrayNode an = context.mapper().createArrayNode();
+ lmEntities.forEach(dm -> an.add(encode(dm, context)));
+ return an;
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LmThresholdOptionCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LmThresholdOptionCodec.java
new file mode 100644
index 0000000..98c0b62
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LmThresholdOptionCodec.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementThreshold.ThresholdOption;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Encode and decode to/from JSON to ThresholdOption object.
+ */
+public class LmThresholdOptionCodec extends JsonCodec<ThresholdOption> {
+
+ @Override
+ public ArrayNode encode(Iterable<ThresholdOption> entities,
+ CodecContext context) {
+ ArrayNode an = context.mapper().createArrayNode();
+ entities.forEach(node -> an.add(node.name()));
+
+ return an;
+ }
+
+ @Override
+ public List<ThresholdOption> decode(ArrayNode json,
+ CodecContext context) {
+ if (json == null) {
+ return null;
+ }
+ List<ThresholdOption> moList = new ArrayList<>();
+ json.forEach(node -> moList.add(ThresholdOption.valueOf(node.asText())));
+ return moList;
+ }
+
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatCodec.java
new file mode 100644
index 0000000..3124976
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatCodec.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStat;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Encode and decode to/from JSON to LossAvailabilityStat object.
+ */
+public class LossAvailabilityStatCodec extends JsonCodec<LossAvailabilityStat> {
+
+ @Override
+ public ObjectNode encode(LossAvailabilityStat laStat, CodecContext context) {
+ checkNotNull(laStat, "LA stat cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put("elapsedTime", laStat.elapsedTime().toString())
+ .put("suspectStatus", String.valueOf(laStat.suspectStatus()));
+
+ if (laStat.forwardHighLoss() != null) {
+ result = result.put("forwardHighLoss",
+ laStat.forwardHighLoss().toString());
+ }
+ if (laStat.backwardHighLoss() != null) {
+ result = result.put("backwardHighLoss",
+ laStat.backwardHighLoss().toString());
+ }
+ if (laStat.forwardConsecutiveHighLoss() != null) {
+ result = result.put("forwardConsecutiveHighLoss",
+ laStat.forwardConsecutiveHighLoss().toString());
+ }
+ if (laStat.backwardConsecutiveHighLoss() != null) {
+ result = result.put("backwardConsecutiveHighLoss",
+ laStat.backwardConsecutiveHighLoss().toString());
+ }
+ if (laStat.forwardAvailable() != null) {
+ result = result.put("forwardAvailable",
+ laStat.forwardAvailable().toString());
+ }
+ if (laStat.backwardAvailable() != null) {
+ result = result.put("backwardAvailable",
+ laStat.backwardAvailable().toString());
+ }
+ if (laStat.forwardUnavailable() != null) {
+ result = result.put("forwardUnavailable",
+ laStat.forwardUnavailable().toString());
+ }
+ if (laStat.backwardUnavailable() != null) {
+ result = result.put("backwardUnavailable",
+ laStat.backwardUnavailable().toString());
+ }
+ if (laStat.backwardMinFrameLossRatio() != null) {
+ result = result.put("backwardMinFrameLossRatio",
+ laStat.backwardMinFrameLossRatio().toString());
+ }
+ if (laStat.backwardMaxFrameLossRatio() != null) {
+ result = result.put("backwardMaxFrameLossRatio",
+ laStat.backwardMaxFrameLossRatio().toString());
+ }
+ if (laStat.backwardAverageFrameLossRatio() != null) {
+ result = result.put("backwardAverageFrameLossRatio",
+ laStat.backwardAverageFrameLossRatio().toString());
+ }
+ if (laStat.forwardMinFrameLossRatio() != null) {
+ result = result.put("forwardMinFrameLossRatio",
+ laStat.forwardMinFrameLossRatio().toString());
+ }
+ if (laStat.forwardMaxFrameLossRatio() != null) {
+ result = result.put("forwardMaxFrameLossRatio",
+ laStat.forwardMaxFrameLossRatio().toString());
+ }
+ if (laStat.forwardAverageFrameLossRatio() != null) {
+ result = result.put("forwardAverageFrameLossRatio",
+ laStat.forwardAverageFrameLossRatio().toString());
+ }
+
+ return result;
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatCurrentCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatCurrentCodec.java
new file mode 100644
index 0000000..a6dc5de
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatCurrentCodec.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStatCurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Encode and decode to/from JSON to LossAvailabilityStatCurrent object.
+ */
+public class LossAvailabilityStatCurrentCodec extends JsonCodec<LossAvailabilityStatCurrent> {
+
+ @Override
+ public ObjectNode encode(LossAvailabilityStatCurrent laCurrent, CodecContext context) {
+ checkNotNull(laCurrent, "LA current cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put("startTime", laCurrent.startTime().toString())
+ .put("elapsedTime", laCurrent.elapsedTime().toString());
+
+ ObjectNode resultAbstract = new LossAvailabilityStatCodec().encode(laCurrent, context);
+ result.setAll(resultAbstract);
+
+ return result;
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatHistoryCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatHistoryCodec.java
new file mode 100644
index 0000000..54e5160
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatHistoryCodec.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStatHistory;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Encode and decode to/from JSON to LossAvailabilityStatHistory object.
+ */
+public class LossAvailabilityStatHistoryCodec extends JsonCodec<LossAvailabilityStatHistory> {
+
+ @Override
+ public ObjectNode encode(LossAvailabilityStatHistory laHistory, CodecContext context) {
+ checkNotNull(laHistory, "LA history cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put("historyId", String.valueOf(laHistory.historyStatsId()))
+ .put("endTime", laHistory.endTime().toString());
+ ObjectNode resultAbstract = new LossAvailabilityStatCodec().encode(laHistory, context);
+ result.setAll(resultAbstract);
+ return result;
+ }
+
+ @Override
+ public ArrayNode encode(Iterable<LossAvailabilityStatHistory> historyEntities, CodecContext context) {
+ ArrayNode an = context.mapper().createArrayNode();
+ historyEntities.forEach(history -> an.add(encode(history, context)));
+ return an;
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatCodec.java
new file mode 100644
index 0000000..eac21e6
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatCodec.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStat;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Encode and decode to/from JSON to LossMeasurementStat object.
+ */
+public class LossMeasurementStatCodec extends JsonCodec<LossMeasurementStat> {
+
+ @Override
+ public ObjectNode encode(LossMeasurementStat lmStat, CodecContext context) {
+ checkNotNull(lmStat, "LM stat cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put("elapsedTime", lmStat.elapsedTime().toString())
+ .put("suspectStatus", String.valueOf(lmStat.suspectStatus()));
+
+ if (lmStat.forwardTransmittedFrames() != null) {
+ result = result.put("forwardTransmittedFrames",
+ lmStat.forwardTransmittedFrames().toString());
+ }
+ if (lmStat.forwardReceivedFrames() != null) {
+ result = result.put("forwardReceivedFrames",
+ lmStat.forwardReceivedFrames().toString());
+ }
+ if (lmStat.forwardMinFrameLossRatio() != null) {
+ result = result.put("forwardMinFrameLossRatio",
+ lmStat.forwardMinFrameLossRatio().toString());
+ }
+ if (lmStat.forwardMaxFrameLossRatio() != null) {
+ result = result.put("forwardMaxFrameLossRatio",
+ lmStat.forwardMaxFrameLossRatio().toString());
+ }
+ if (lmStat.forwardAverageFrameLossRatio() != null) {
+ result = result.put("forwardAverageFrameLossRatio",
+ lmStat.forwardAverageFrameLossRatio().toString());
+ }
+ if (lmStat.backwardTransmittedFrames() != null) {
+ result = result.put("backwardTransmittedFrames",
+ lmStat.backwardTransmittedFrames().toString());
+ }
+ if (lmStat.backwardReceivedFrames() != null) {
+ result = result.put("backwardReceivedFrames",
+ lmStat.backwardReceivedFrames().toString());
+ }
+ if (lmStat.backwardMinFrameLossRatio() != null) {
+ result = result.put("backwardMinFrameLossRatio",
+ lmStat.backwardMinFrameLossRatio().toString());
+ }
+ if (lmStat.backwardMaxFrameLossRatio() != null) {
+ result = result.put("backwardMaxFrameLossRatio",
+ lmStat.backwardMaxFrameLossRatio().toString());
+ }
+ if (lmStat.backwardAverageFrameLossRatio() != null) {
+ result = result.put("backwardAverageFrameLossRatio",
+ lmStat.backwardAverageFrameLossRatio().toString());
+ }
+ if (lmStat.soamPdusSent() != null) {
+ result = result.put("soamPdusSent",
+ lmStat.soamPdusSent().toString());
+ }
+ if (lmStat.soamPdusReceived() != null) {
+ result.put("soamPdusReceived",
+ lmStat.soamPdusReceived().toString());
+ }
+
+ return result;
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatCurrentCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatCurrentCodec.java
new file mode 100644
index 0000000..d525493
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatCurrentCodec.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatCurrent;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Encode and decode to/from JSON to LossMeasurementStatCurrent object.
+ */
+public class LossMeasurementStatCurrentCodec extends JsonCodec<LossMeasurementStatCurrent> {
+
+ @Override
+ public ObjectNode encode(LossMeasurementStatCurrent lmCurrent, CodecContext context) {
+ checkNotNull(lmCurrent, "LM current cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put("startTime", lmCurrent.startTime().toString())
+ .put("elapsedTime", lmCurrent.elapsedTime().toString());
+
+ ObjectNode resultAbstract = new LossMeasurementStatCodec().encode(lmCurrent, context);
+ result.setAll(resultAbstract);
+
+ return result;
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatHistoryCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatHistoryCodec.java
new file mode 100644
index 0000000..e4ec282
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatHistoryCodec.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatHistory;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Encode and decode to/from JSON to LossMeasurementStatHistory object.
+ */
+public class LossMeasurementStatHistoryCodec extends JsonCodec<LossMeasurementStatHistory> {
+
+ @Override
+ public ObjectNode encode(LossMeasurementStatHistory lmHistory, CodecContext context) {
+ checkNotNull(lmHistory, "LM history cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put("historyId", String.valueOf(lmHistory.historyStatsId()))
+ .put("endTime", lmHistory.endTime().toString());
+ ObjectNode resultAbstract = new LossMeasurementStatCodec().encode(lmHistory, context);
+ result.setAll(resultAbstract);
+ return result;
+ }
+
+ @Override
+ public ArrayNode encode(Iterable<LossMeasurementStatHistory> historyEntities, CodecContext context) {
+ ArrayNode an = context.mapper().createArrayNode();
+ historyEntities.forEach(history -> an.add(encode(history, context)));
+ return an;
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementThresholdCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementThresholdCodec.java
new file mode 100644
index 0000000..3a17f94
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementThresholdCodec.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.MilliPct;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamId;
+import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementThreshold;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+import static org.onosproject.incubator.net.l2monitoring.soam.loss.DefaultLmThreshold.*;
+
+/**
+ * Encode and decode to/from JSON to LossMeasurementThreshold object.
+ */
+public class LossMeasurementThresholdCodec extends JsonCodec<LossMeasurementThreshold> {
+ static final String MEASUREDFLRFORWARD = "measuredFlrForward";
+ static final String MAXFLRFORWARD = "maxFlrForward";
+ static final String AVERAGEFLRFORWARD = "averageFlrForward";
+ static final String MEASUREDFLRBACKWARD = "measuredFlrBackward";
+ static final String MAXFLRBACKWARD = "maxFlrBackward";
+ static final String AVERAGEFLRBACKWARD = "averageFlrBackward";
+ static final String FORWARDHIGHLOSS = "forwardHighLoss";
+ static final String FORWARDCONSECUTIVEHIGHLOSS = "forwardConsecutiveHighLoss";
+ static final String BACKWARDHIGHLOSS = "backwardHighLoss";
+ static final String BACKWARDCONSECUTIVEHIGHLOSS = "backwardConsecutiveHighLoss";
+ static final String FORWARDUNAVAILABLECOUNT = "forwardUnavailableCount";
+ static final String FORWARDAVAILABLERATIO = "forwardAvailableRatio";
+ static final String BACKWARDUNAVAILABLECOUNT = "backwardUnavailableCount";
+ static final String BACKWARDAVAILABLERATIO = "backwardAvailableRatio";
+ static final String THRESHOLDOPTIONS = "thresholdOptions";
+
+ @Override
+ public ObjectNode encode(LossMeasurementThreshold lmt, CodecContext context) {
+ checkNotNull(lmt, "LM thresholds cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put("id", lmt.thresholdId().value());
+
+ if (lmt.thresholds() != null) {
+ result.set(THRESHOLDOPTIONS, new LmThresholdOptionCodec()
+ .encode(lmt.thresholds(), context));
+ }
+
+ if (lmt.measuredFlrForward() != null) {
+ result.put(MEASUREDFLRFORWARD, lmt.measuredFlrForward().percentValue());
+ }
+ if (lmt.maxFlrForward() != null) {
+ result.put(MAXFLRFORWARD, lmt.maxFlrForward().percentValue());
+ }
+ if (lmt.averageFlrForward() != null) {
+ result.put(AVERAGEFLRFORWARD, lmt.averageFlrForward().percentValue());
+ }
+ if (lmt.measuredFlrBackward() != null) {
+ result.put(MEASUREDFLRBACKWARD, lmt.measuredFlrBackward().percentValue());
+ }
+ if (lmt.maxFlrBackward() != null) {
+ result.put(MAXFLRBACKWARD, lmt.maxFlrBackward().percentValue());
+ }
+ if (lmt.averageFlrBackward() != null) {
+ result.put(AVERAGEFLRBACKWARD, lmt.averageFlrBackward().percentValue());
+ }
+ if (lmt.forwardHighLoss() != null) {
+ result.put(FORWARDHIGHLOSS, lmt.forwardHighLoss().longValue());
+ }
+ if (lmt.forwardConsecutiveHighLoss() != null) {
+ result.put(FORWARDCONSECUTIVEHIGHLOSS, lmt.measuredFlrForward().longValue());
+ }
+ if (lmt.backwardHighLoss() != null) {
+ result.put(BACKWARDHIGHLOSS, lmt.backwardHighLoss().longValue());
+ }
+ if (lmt.backwardConsecutiveHighLoss() != null) {
+ result.put(BACKWARDCONSECUTIVEHIGHLOSS, lmt.backwardConsecutiveHighLoss().longValue());
+ }
+ if (lmt.forwardUnavailableCount() != null) {
+ result.put(FORWARDUNAVAILABLECOUNT, lmt.forwardUnavailableCount().longValue());
+ }
+ if (lmt.forwardAvailableRatio() != null) {
+ result.put(FORWARDAVAILABLERATIO, lmt.forwardAvailableRatio().percentValue());
+ }
+ if (lmt.backwardUnavailableCount() != null) {
+ result.put(BACKWARDUNAVAILABLECOUNT, lmt.backwardUnavailableCount().longValue());
+ }
+ if (lmt.backwardAvailableRatio() != null) {
+ result.put(BACKWARDAVAILABLERATIO, lmt.backwardAvailableRatio().percentValue());
+ }
+
+ return result;
+ }
+
+ @Override
+ public List<LossMeasurementThreshold> decode(ArrayNode json, CodecContext context) {
+ if (json == null) {
+ return null;
+ }
+ List<LossMeasurementThreshold> thrList = new ArrayList<>();
+ json.forEach(node -> thrList.add(decode((ObjectNode) node, context)));
+ return thrList;
+ }
+
+ @Override
+ public LossMeasurementThreshold decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ JsonNode thrNode = json.get("threshold");
+
+ SoamId thresholdId = SoamId.valueOf(nullIsIllegal(thrNode.get("id"),
+ "thresholdId must not be null").asInt());
+ LossMeasurementThreshold.LmThresholdBuilder builder = builder(thresholdId);
+
+ if (thrNode.get("thresholds") != null) {
+ context.codec(ThresholdOption.class)
+ .decode((ArrayNode) (thrNode.get("thresholds")), context)
+ .forEach(builder::addToThreshold);
+ }
+
+ if (thrNode.get(MEASUREDFLRFORWARD) != null) {
+ builder.measuredFlrForward(MilliPct.ofPercent(
+ (float) thrNode.get(MEASUREDFLRFORWARD).asDouble()));
+ }
+ if (thrNode.get(MAXFLRFORWARD) != null) {
+ builder.maxFlrForward(MilliPct.ofPercent(
+ (float) thrNode.get(MAXFLRFORWARD).asDouble()));
+ }
+ if (thrNode.get(AVERAGEFLRFORWARD) != null) {
+ builder.averageFlrForward(MilliPct.ofPercent(
+ (float) thrNode.get(AVERAGEFLRFORWARD).asDouble()));
+ }
+ if (thrNode.get(MEASUREDFLRBACKWARD) != null) {
+ builder.measuredFlrBackward(MilliPct.ofPercent(
+ (float) thrNode.get(MEASUREDFLRBACKWARD).asDouble()));
+ }
+ if (thrNode.get(MAXFLRBACKWARD) != null) {
+ builder.maxFlrBackward(MilliPct.ofPercent(
+ (float) thrNode.get(MAXFLRBACKWARD).asDouble()));
+ }
+ if (thrNode.get(AVERAGEFLRBACKWARD) != null) {
+ builder.averageFlrBackward(MilliPct.ofPercent(
+ (float) thrNode.get(AVERAGEFLRBACKWARD).asDouble()));
+ }
+ if (thrNode.get(FORWARDHIGHLOSS) != null) {
+ builder.forwardHighLoss(thrNode.get(FORWARDHIGHLOSS).asLong());
+ }
+ if (thrNode.get(FORWARDCONSECUTIVEHIGHLOSS) != null) {
+ builder.forwardConsecutiveHighLoss(thrNode.get(FORWARDCONSECUTIVEHIGHLOSS).asLong());
+ }
+ if (thrNode.get(BACKWARDHIGHLOSS) != null) {
+ builder.backwardHighLoss(thrNode.get(BACKWARDHIGHLOSS).asLong());
+ }
+ if (thrNode.get(BACKWARDCONSECUTIVEHIGHLOSS) != null) {
+ builder.backwardConsecutiveHighLoss(thrNode.get(BACKWARDCONSECUTIVEHIGHLOSS).asLong());
+ }
+ if (thrNode.get(FORWARDUNAVAILABLECOUNT) != null) {
+ builder.forwardUnavailableCount(thrNode.get(FORWARDUNAVAILABLECOUNT).asLong());
+ }
+ if (thrNode.get(FORWARDAVAILABLERATIO) != null) {
+ builder.forwardAvailableRatio(MilliPct.ofPercent(
+ (float) thrNode.get(FORWARDAVAILABLERATIO).asDouble()));
+ }
+ if (thrNode.get(BACKWARDUNAVAILABLECOUNT) != null) {
+ builder.backwardUnavailableCount(thrNode.get(BACKWARDUNAVAILABLECOUNT).asLong());
+ }
+ if (thrNode.get(BACKWARDAVAILABLERATIO) != null) {
+ builder.backwardAvailableRatio(MilliPct.ofPercent(
+ (float) thrNode.get(BACKWARDAVAILABLERATIO).asDouble()));
+ }
+
+ return builder.build();
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/StartTimeCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/StartTimeCodec.java
new file mode 100644
index 0000000..f84bffe
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/StartTimeCodec.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import java.time.Duration;
+import java.time.OffsetDateTime;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.StartTime;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Encode and decode to/from JSON to StartTime object.
+ */
+public class StartTimeCodec extends JsonCodec<StartTime> {
+
+ @Override
+ public StartTime decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ if (json.get("immediate") != null) {
+ return StartTime.immediate();
+ } else if (json.get("absolute") != null) {
+ if (json.get("absolute").get("start-time") != null) {
+ return StartTime.absolute(OffsetDateTime
+ .parse(json.get("absolute").get("start-time").asText())
+ .toInstant());
+ }
+ throw new IllegalArgumentException("StartTime absolute must contain "
+ + "a start-time in date-time format with offset");
+ } else if (json.get("relative") != null) {
+ if (json.get("relative").get("start-time") != null) {
+ return StartTime.relative(Duration.parse(json.get("relative").get("start-time").asText()));
+ }
+ throw new IllegalArgumentException("StartTime relative must contain a start-time duration");
+ } else {
+ throw new IllegalArgumentException("StartTime must be either immediate, absolute or relative");
+ }
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/StopTimeCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/StopTimeCodec.java
new file mode 100644
index 0000000..30a1538
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/StopTimeCodec.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.onosproject.soam.web;
+
+import java.time.Duration;
+import java.time.OffsetDateTime;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.incubator.net.l2monitoring.soam.StopTime;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Encode and decode to/from JSON to StopTime object.
+ */
+public class StopTimeCodec extends JsonCodec<StopTime> {
+
+ @Override
+ public StopTime decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ if (json.get("none") != null) {
+ return StopTime.none();
+ } else if (json.get("absolute") != null) {
+ if (json.get("absolute").get("stop-time") != null) {
+ return StopTime.absolute(OffsetDateTime
+ .parse(json.get("absolute").get("stop-time").asText())
+ .toInstant());
+ }
+ throw new IllegalArgumentException("StopTime absolute must contain "
+ + "a stop-time in date-time format with offset");
+ } else if (json.get("relative") != null) {
+ if (json.get("relative").get("stop-time") != null) {
+ return StopTime.relative(Duration.parse(json.get("relative").get("stop-time").asText()));
+ }
+ throw new IllegalArgumentException("StopTime relative must contain a stop-time duration");
+ } else {
+ throw new IllegalArgumentException("StopTime must be either none, absolute or relative");
+ }
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/package-info.java b/apps/cfm/src/main/java/org/onosproject/soam/web/package-info.java
new file mode 100644
index 0000000..473be24
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/soam/web/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.
+ */
+/**
+ * Codecs for converting SOAM objects to and from JSON.
+ */
+package org.onosproject.soam.web;
\ No newline at end of file