*/
package org.opendaylight.protocol.pcep.ietf.stateful07;
-import io.netty.buffer.ByteBuf;
+import static com.google.common.base.Preconditions.checkArgument;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.ArrayList;
import java.util.List;
-
+import java.util.Optional;
import org.opendaylight.protocol.pcep.spi.AbstractMessageParser;
-import org.opendaylight.protocol.pcep.spi.ObjectHandlerRegistry;
+import org.opendaylight.protocol.pcep.spi.MessageUtil;
+import org.opendaylight.protocol.pcep.spi.ObjectRegistry;
import org.opendaylight.protocol.pcep.spi.PCEPDeserializerException;
import org.opendaylight.protocol.pcep.spi.PCEPErrors;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcupd;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PcupdBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.Lsp;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.PcupdMessageBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.Updates;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.UpdatesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.updates.Path;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.updates.PathBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.Srp;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Object;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.bandwidth.object.Bandwidth;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.Ero;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.include.route.object.Iro;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.attributes.Metrics;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.attributes.MetricsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lspa.object.Lspa;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.metric.object.Metric;
-
-import com.google.common.collect.Lists;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.Pcupd;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.PcupdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.lsp.object.Lsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.pcupd.message.PcupdMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.pcupd.message.pcupd.message.Updates;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.pcupd.message.pcupd.message.UpdatesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.pcupd.message.pcupd.message.updates.Path;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.pcupd.message.pcupd.message.updates.PathBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.srp.object.Srp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Message;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Object;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.bandwidth.object.Bandwidth;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.Ero;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.include.route.object.Iro;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.Metrics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.MetricsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lspa.object.Lspa;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.metric.object.Metric;
/**
- * Parser for {@link Pcupd}
+ * Parser for {@link Pcupd}.
*/
public class Stateful07PCUpdateRequestMessageParser extends AbstractMessageParser {
- public static final int TYPE = 11;
-
- public Stateful07PCUpdateRequestMessageParser(final ObjectHandlerRegistry registry) {
- super(registry);
- }
-
- @Override
- public void serializeMessage(final Message message, final ByteBuf buffer) {
- if (!(message instanceof Pcupd)) {
- throw new IllegalArgumentException("Wrong instance of PCEPMessage. Passed instance of " + message.getClass()
- + ". Nedded PcupdMessage.");
- }
- final Pcupd msg = (Pcupd) message;
- final List<Updates> updates = msg.getPcupdMessage().getUpdates();
- for (final Updates update : updates) {
- buffer.writeBytes(serializeObject(update.getSrp()));
- buffer.writeBytes(serializeObject(update.getLsp()));
- final Path p = update.getPath();
- if (p != null) {
- buffer.writeBytes(serializeObject(p.getEro()));
- if (p.getLspa() != null) {
- buffer.writeBytes(serializeObject(p.getLspa()));
- }
- if (p.getBandwidth() != null) {
- buffer.writeBytes(serializeObject(p.getBandwidth()));
- }
- if (p.getMetrics() != null && !p.getMetrics().isEmpty()) {
- for (final Metrics m : p.getMetrics()) {
- buffer.writeBytes(serializeObject(m.getMetric()));
- }
- }
- if (p.getIro() != null) {
- buffer.writeBytes(serializeObject(p.getIro()));
- }
- }
- }
- }
-
- @Override
- protected Message validate(final List<Object> objects, final List<Message> errors) throws PCEPDeserializerException {
- if (objects == null) {
- throw new IllegalArgumentException("Passed list can't be null.");
- }
- if (objects.isEmpty()) {
- throw new PCEPDeserializerException("Pcup message cannot be empty.");
- }
-
- final List<Updates> updateRequests = Lists.newArrayList();
-
- while (!objects.isEmpty()) {
- final Updates update = getValidUpdates(objects, errors);
- if (update != null) {
- updateRequests.add(update);
- }
- }
- if (!objects.isEmpty()) {
- throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
- }
- return new PcupdBuilder().setPcupdMessage(new PcupdMessageBuilder().setUpdates(updateRequests).build()).build();
- }
-
- private Updates getValidUpdates(final List<Object> objects, final List<Message> errors) {
- final UpdatesBuilder builder = new UpdatesBuilder();
- if (objects.get(0) instanceof Srp) {
- builder.setSrp((Srp) objects.get(0));
- objects.remove(0);
- } else {
- errors.add(createErrorMsg(PCEPErrors.SRP_MISSING));
- return null;
- }
- if (objects.get(0) instanceof Lsp) {
- builder.setLsp((Lsp) objects.get(0));
- objects.remove(0);
- } else {
- errors.add(createErrorMsg(PCEPErrors.LSP_MISSING));
- return null;
- }
- if (!objects.isEmpty()) {
- final PathBuilder pBuilder = new PathBuilder();
- if (objects.get(0) instanceof Ero) {
- pBuilder.setEro((Ero) objects.get(0));
- objects.remove(0);
- } else {
- errors.add(createErrorMsg(PCEPErrors.ERO_MISSING));
- return null;
- }
- parsePath(objects, pBuilder);
- builder.setPath(pBuilder.build());
- }
- return builder.build();
- }
-
- private void parsePath(final List<Object> objects, final PathBuilder pBuilder) {
- final List<Metrics> pathMetrics = Lists.newArrayList();
- Object obj;
- State state = State.Init;
- while (!objects.isEmpty() && !state.equals(State.End)) {
- obj = objects.get(0);
- switch (state) {
- case Init:
- state = State.LspaIn;
- if (obj instanceof Lspa) {
- pBuilder.setLspa((Lspa) obj);
- break;
- }
- case LspaIn:
- state = State.BandwidthIn;
- if (obj instanceof Bandwidth) {
- pBuilder.setBandwidth((Bandwidth) obj);
- break;
- }
- case BandwidthIn:
- state = State.MetricIn;
- if (obj instanceof Metric) {
- pathMetrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
- state = State.BandwidthIn;
- break;
- }
- case MetricIn:
- state = State.IroIn;
- if (obj instanceof Iro) {
- pBuilder.setIro((Iro) obj);
- break;
- }
- case IroIn:
- state = State.End;
- break;
- case End:
- break;
- }
- if (!state.equals(State.End)) {
- objects.remove(0);
- }
- }
- if (!pathMetrics.isEmpty()) {
- pBuilder.setMetrics(pathMetrics);
- }
- }
-
- private enum State {
- Init, LspaIn, BandwidthIn, MetricIn, IroIn, End
- }
-
- @Override
- public int getMessageType() {
- return TYPE;
- }
+ public static final int TYPE = 11;
+
+ public Stateful07PCUpdateRequestMessageParser(final ObjectRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public void serializeMessage(final Message message, final ByteBuf out) {
+ checkArgument(message instanceof Pcupd, "Wrong instance of Message. Passed instance of %s. Need Pcupd.",
+ message.getClass());
+ final Pcupd msg = (Pcupd) message;
+ final List<Updates> updates = msg.getPcupdMessage().getUpdates();
+ final ByteBuf buffer = Unpooled.buffer();
+ for (final Updates update : updates) {
+ serializeUpdate(update, buffer);
+ }
+ MessageUtil.formatMessage(TYPE, buffer, out);
+ }
+
+ protected void serializeUpdate(final Updates update, final ByteBuf buffer) {
+ serializeObject(update.getSrp(), buffer);
+ serializeObject(update.getLsp(), buffer);
+ final Path p = update.getPath();
+ if (p != null) {
+ serializeObject(p.getEro(), buffer);
+ serializeObject(p.getLspa(), buffer);
+ serializeObject(p.getBandwidth(), buffer);
+ serializeObject(p.getReoptimizationBandwidth(), buffer);
+ if (p.getMetrics() != null) {
+ for (final Metrics m : p.getMetrics()) {
+ serializeObject(m.getMetric(), buffer);
+ }
+ }
+ serializeObject(p.getIro(), buffer);
+ }
+ }
+
+ @Override
+ protected Message validate(final List<Object> objects, final List<Message> errors)
+ throws PCEPDeserializerException {
+ checkArgument(objects != null, "Passed list can't be null.");
+ if (objects.isEmpty()) {
+ throw new PCEPDeserializerException("Pcup message cannot be empty.");
+ }
+
+ final List<Updates> updateRequests = new ArrayList<>();
+
+ while (!objects.isEmpty()) {
+ final Updates upd = getValidUpdates(objects, errors);
+ if (upd != null) {
+ updateRequests.add(upd);
+ }
+ }
+ if (!objects.isEmpty()) {
+ throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+ }
+ return new PcupdBuilder().setPcupdMessage(new PcupdMessageBuilder().setUpdates(updateRequests).build()).build();
+ }
+
+ protected Updates getValidUpdates(final List<Object> objects, final List<Message> errors) {
+ final UpdatesBuilder builder = new UpdatesBuilder();
+
+ Object object = objects.remove(0);
+ if (object instanceof Srp) {
+ builder.setSrp((Srp) object);
+ if (objects.isEmpty()) {
+ object = null;
+ } else {
+ object = objects.remove(0);
+ }
+ } else {
+ errors.add(createErrorMsg(PCEPErrors.SRP_MISSING, Optional.empty()));
+ }
+
+ if (validateLsp(object, errors, builder)) {
+ if (!objects.isEmpty()) {
+ if (!validatePath(objects, errors, builder)) {
+ return null;
+ }
+ }
+
+ return builder.build();
+ }
+ return null;
+ }
+
+ private static boolean validateLsp(final Object object, final List<Message> errors, final UpdatesBuilder builder) {
+ if (object instanceof Lsp) {
+ builder.setLsp((Lsp) object);
+ } else {
+ errors.add(createErrorMsg(PCEPErrors.LSP_MISSING, Optional.empty()));
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean validatePath(final List<Object> objects, final List<Message> errors,
+ final UpdatesBuilder builder) {
+ final PathBuilder pBuilder = new PathBuilder();
+ Object object = objects.remove(0);
+ if (object instanceof Ero) {
+ pBuilder.setEro((Ero) object);
+ } else {
+ errors.add(createErrorMsg(PCEPErrors.ERO_MISSING, Optional.empty()));
+ return false;
+ }
+ parsePath(objects, pBuilder);
+ builder.setPath(pBuilder.build());
+ return true;
+ }
+
+ private static void parsePath(final List<Object> objects, final PathBuilder pathBuilder) {
+ final List<Metrics> pathMetrics = new ArrayList<>();
+ Object obj;
+ State state = State.INIT;
+ while (!objects.isEmpty() && !state.equals(State.END)) {
+ obj = objects.get(0);
+ state = insertObject(state,obj, pathBuilder, pathMetrics);
+ if (!state.equals(State.END)) {
+ objects.remove(0);
+ }
+ }
+ if (!pathMetrics.isEmpty()) {
+ pathBuilder.setMetrics(pathMetrics);
+ }
+ }
+
+ private static State insertObject(final State state, final Object obj, final PathBuilder pathBuilder,
+ final List<Metrics> pathMetrics) {
+ switch (state) {
+ case INIT:
+ if (obj instanceof Lspa) {
+ pathBuilder.setLspa((Lspa) obj);
+ return State.LSPA_IN;
+ }
+ // fall through
+ case LSPA_IN:
+ if (obj instanceof Bandwidth) {
+ pathBuilder.setBandwidth((Bandwidth) obj);
+ return State.LSPA_IN;
+ }
+ if (obj instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109
+ .reoptimization.bandwidth.object.ReoptimizationBandwidth) {
+ pathBuilder.setReoptimizationBandwidth((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns
+ .yang.pcep.types.rev181109.reoptimization.bandwidth.object.ReoptimizationBandwidth) obj);
+ return State.LSPA_IN;
+ }
+ // fall through
+ case BANDWIDTH_IN:
+ if (obj instanceof Metric) {
+ pathMetrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
+ return State.BANDWIDTH_IN;
+ }
+ // fall through
+ case METRIC_IN:
+ if (obj instanceof Iro) {
+ pathBuilder.setIro((Iro) obj);
+ return State.IRO_IN;
+ }
+ // fall through
+ case IRO_IN:
+ case END:
+ return State.END;
+ default:
+ return state;
+ }
+ }
+
+ private enum State {
+ INIT, LSPA_IN, BANDWIDTH_IN, METRIC_IN, IRO_IN, END
+ }
}