Rework parser infrastructure to support partial message processing
[bgpcep.git] / pcep / impl / src / main / java / org / opendaylight / protocol / pcep / impl / message / PCEPNotificationMessageParser.java
index c39589f07971f866dbe5c4924e21da3fc9c5f0e4..068e25a91d296de35ca2d3d064dccd4e84b90843 100644 (file)
@@ -17,20 +17,22 @@ import org.opendaylight.protocol.pcep.PCEPDocumentedException;
 import org.opendaylight.protocol.pcep.PCEPErrorMapping;
 import org.opendaylight.protocol.pcep.PCEPErrors;
 import org.opendaylight.protocol.pcep.UnknownObject;
-import org.opendaylight.protocol.pcep.spi.AbstractMessageParser;
-import org.opendaylight.protocol.pcep.spi.HandlerRegistry;
+import org.opendaylight.protocol.pcep.spi.ObjectHandlerRegistry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.PcerrBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.PcntfBuilder;
 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.NotificationObject;
 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.PcntfMessage;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.RpObject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.notification.object.CNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcep.error.object.ErrorObjectBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.PcerrMessageBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcerr.message.pcerr.message.ErrorsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcntf.message.PcntfMessageBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcntf.message.pcntf.message.notifications.Notifications;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcntf.message.pcntf.message.notifications.NotificationsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcntf.message.pcntf.message.notifications.Rps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcntf.message.pcntf.message.notifications.RpsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rp.object.Rp;
 
 import com.google.common.collect.Lists;
 
@@ -39,48 +41,45 @@ import com.google.common.collect.Lists;
  */
 public class PCEPNotificationMessageParser extends AbstractMessageParser {
 
-       private final int TYPE = 5;
+       public static final int TYPE = 5;
 
-       public PCEPNotificationMessageParser(final HandlerRegistry registry) {
+       public PCEPNotificationMessageParser(final ObjectHandlerRegistry registry) {
                super(registry);
        }
 
        @Override
        public void serializeMessage(final Message message, final ByteBuf buffer) {
-               if (!(message instanceof PcntfMessage))
+               if (!(message instanceof PcntfMessage)) {
                        throw new IllegalArgumentException("Wrong instance of Message. Passed instance of " + message.getClass()
                                        + ". Needed PcntfMessage.");
+               }
                final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcntf.message.PcntfMessage msg = ((PcntfMessage) message).getPcntfMessage();
 
                for (final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcntf.message.pcntf.message.Notifications n : msg.getNotifications()) {
                        if (n.getRps() != null && !n.getRps().isEmpty()) {
                                for (final Rps rps : n.getRps()) {
-                                       buffer.writeBytes(serializeObject(rps));
+                                       buffer.writeBytes(serializeObject(rps.getRp()));
                                }
                        }
                        if (n.getNotifications() == null || n.getNotifications().isEmpty()) {
                                throw new IllegalArgumentException("Message must contain at least one notification object");
                        } else {
                                for (final Notifications not : n.getNotifications()) {
-                                       buffer.writeBytes(serializeObject(not));
+                                       buffer.writeBytes(serializeObject(not.getCNotification()));
                                }
                        }
                }
        }
 
        @Override
-       public Message parseMessage(final byte[] buffer) throws PCEPDeserializerException, PCEPDocumentedException {
-               if (buffer == null || buffer.length == 0) {
-                       throw new PCEPDeserializerException("Notification message cannot be empty.");
+       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.");
                }
-               final List<Object> objs = parseObjects(buffer);
 
-               return validate(objs);
-       }
-
-       public Message validate(final List<Object> objects) throws PCEPDeserializerException {
-               if (objects == null)
-                       throw new IllegalArgumentException("Passed list can't be null.");
+               if (objects.isEmpty()) {
+                       throw new PCEPDeserializerException("Notification message cannot be empty.");
+               }
 
                final PCEPErrorMapping maping = PCEPErrorMapping.getInstance();
 
@@ -92,22 +91,26 @@ public class PCEPNotificationMessageParser extends AbstractMessageParser {
                                comObj = getValidNotificationComposite(objects);
                        } catch (final PCEPDocumentedException e) {
                                final PcerrMessageBuilder b = new PcerrMessageBuilder();
-                               b.setErrors(Arrays.asList(new ErrorsBuilder().setType(maping.getFromErrorsEnum(e.getError()).type).setValue(
-                                               maping.getFromErrorsEnum(e.getError()).value).build()));
+                               b.setErrors(Arrays.asList(new ErrorsBuilder().setErrorObject(
+                                               new ErrorObjectBuilder().setType(maping.getFromErrorsEnum(e.getError()).type).setValue(
+                                                               maping.getFromErrorsEnum(e.getError()).value).build()).build()));
                                return new PcerrBuilder().setPcerrMessage(b.build()).build();
                        }
 
-                       if (comObj == null)
+                       if (comObj == null) {
                                break;
+                       }
 
                        compositeNotifications.add(comObj);
                }
 
-               if (compositeNotifications.isEmpty())
-                       throw new PCEPDeserializerException("Atleast one CompositeNotifiObject is mandatory.");
+               if (compositeNotifications.isEmpty()) {
+                       throw new PCEPDeserializerException("Atleast one Notifications is mandatory.");
+               }
 
-               if (!objects.isEmpty())
+               if (!objects.isEmpty()) {
                        throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
+               }
 
                return new PcntfBuilder().setPcntfMessage(new PcntfMessageBuilder().setNotifications(compositeNotifications).build()).build();
        }
@@ -118,49 +121,59 @@ public class PCEPNotificationMessageParser extends AbstractMessageParser {
                final List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcntf.message.pcntf.message.notifications.Notifications> notifications = Lists.newArrayList();
                Object obj;
 
-               int state = 1;
-               while (!objects.isEmpty()) {
+               State state = State.Init;
+               while (!objects.isEmpty() && !state.equals(State.End)) {
                        obj = objects.get(0);
 
-                       if (obj instanceof UnknownObject)
+                       if (obj instanceof UnknownObject) {
                                throw new PCEPDocumentedException("Unknown object", ((UnknownObject) obj).getError());
+                       }
 
                        switch (state) {
-                       case 1:
-                               state = 2;
-                               if (obj instanceof RpObject) {
-                                       final RpObject rp = (RpObject) obj;
-                                       if (rp.isProcessingRule())
+                       case Init:
+                               state = State.RpIn;
+                               if (obj instanceof Rp) {
+                                       final Rp rp = (Rp) obj;
+                                       if (rp.isProcessingRule()) {
                                                throw new PCEPDocumentedException("Invalid setting of P flag.", PCEPErrors.P_FLAG_NOT_SET);
-                                       requestParameters.add((Rps) rp);
-                                       state = 1;
+                                       }
+                                       requestParameters.add(new RpsBuilder().setRp(rp).build());
+                                       state = State.Init;
                                        break;
                                }
-                       case 2:
-                               if (obj instanceof NotificationObject) {
-                                       final NotificationObject n = (NotificationObject) obj;
-                                       notifications.add((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcntf.message.pcntf.message.notifications.Notifications) n);
-                                       state = 2;
+                       case RpIn:
+                               state = State.NotificationIn;
+                               if (obj instanceof CNotification) {
+                                       final CNotification n = (CNotification) obj;
+                                       notifications.add(new NotificationsBuilder().setCNotification(n).build());
+                                       state = State.RpIn;
                                        break;
                                }
-                               state = 3;
-                       }
-
-                       if (state == 3)
+                       case NotificationIn:
+                               state = State.End;
                                break;
-
-                       objects.remove(obj);
+                       case End:
+                               break;
+                       }
+                       if (!state.equals(State.End)) {
+                               objects.remove(0);
+                       }
                }
 
-               if (notifications.isEmpty())
+               if (notifications.isEmpty()) {
                        return null;
+               }
 
                return new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcntf.message.pcntf.message.NotificationsBuilder().setNotifications(
                                notifications).setRps(requestParameters).build();
        }
 
+       private enum State {
+               Init, RpIn, NotificationIn, End
+       }
+
        @Override
        public int getMessageType() {
-               return this.TYPE;
+               return TYPE;
        }
 }