Rework parser infrastructure to support partial message processing
[bgpcep.git] / pcep / impl / src / main / java / org / opendaylight / protocol / pcep / impl / message / PCEPReportMessageParser.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.protocol.pcep.impl.message;
9
10 import io.netty.buffer.ByteBuf;
11
12 import java.util.List;
13
14 import org.opendaylight.protocol.pcep.PCEPDeserializerException;
15 import org.opendaylight.protocol.pcep.PCEPDocumentedException;
16 import org.opendaylight.protocol.pcep.PCEPErrors;
17 import org.opendaylight.protocol.pcep.UnknownObject;
18 import org.opendaylight.protocol.pcep.spi.ObjectHandlerRegistry;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcrpt;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.PcrptBuilder;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Object;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.bandwidth.object.Bandwidth;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.Ero;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.include.route.object.Iro;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.attributes.Metrics;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.attributes.MetricsBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.object.Lsp;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lspa.object.Lspa;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.metric.object.Metric;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrpt.message.PcrptMessageBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrpt.message.pcrpt.message.Reports;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrpt.message.pcrpt.message.ReportsBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrpt.message.pcrpt.message.reports.Path;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrpt.message.pcrpt.message.reports.PathBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.reported.route.object.Rro;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.srp.object.Srp;
38
39 import com.google.common.collect.Lists;
40
41 /**
42  * Parser for {@link Pcrpt}
43  */
44 public class PCEPReportMessageParser extends AbstractMessageParser {
45
46         public static final int TYPE = 10;
47
48         public PCEPReportMessageParser(final ObjectHandlerRegistry registry) {
49                 super(registry);
50         }
51
52         @Override
53         public void serializeMessage(final Message message, final ByteBuf buffer) {
54                 if (!(message instanceof Pcrpt)) {
55                         throw new IllegalArgumentException("Wrong instance of Message. Passed instance of " + message.getClass()
56                                         + ". Nedded PcrptMessage.");
57                 }
58                 final Pcrpt msg = (Pcrpt) message;
59                 final List<Reports> reports = msg.getPcrptMessage().getReports();
60                 for (final Reports report : reports) {
61                         if (report.getSrp() != null) {
62                                 buffer.writeBytes(serializeObject(report.getSrp()));
63                         }
64                         buffer.writeBytes(serializeObject(report.getLsp()));
65                         final Path p = report.getPath();
66                         if (p != null) {
67                                 if (p.getEro() != null) {
68                                         buffer.writeBytes(serializeObject(p.getEro()));
69                                 }
70                                 if (p.getLspa() != null) {
71                                         buffer.writeBytes(serializeObject(p.getLspa()));
72                                 }
73                                 if (p.getBandwidth() != null) {
74                                         buffer.writeBytes(serializeObject(p.getBandwidth()));
75                                 }
76                                 if (p.getMetrics() != null && !p.getMetrics().isEmpty()) {
77                                         for (final Metrics m : p.getMetrics()) {
78                                                 buffer.writeBytes(serializeObject(m.getMetric()));
79                                         }
80                                 }
81                                 if (p.getIro() != null) {
82                                         buffer.writeBytes(serializeObject(p.getIro()));
83                                 }
84                                 if (p.getRro() != null) {
85                                         buffer.writeBytes(serializeObject(p.getRro()));
86                                 }
87                         }
88                 }
89         }
90
91         @Override
92         public Message validate(final List<Object> objects, final List<Message> errors) throws PCEPDeserializerException, PCEPDocumentedException {
93                 if (objects == null) {
94                         throw new IllegalArgumentException("Passed list can't be null.");
95                 }
96                 if (objects.isEmpty()) {
97                         throw new PCEPDeserializerException("Pcrpt message cannot be empty.");
98                 }
99
100                 final List<Reports> reports = Lists.newArrayList();
101
102                 while (!objects.isEmpty()) {
103                         final Reports report = getValidReports(objects);
104                         if (reports != null) {
105                                 reports.add(report);
106                         }
107                 }
108
109                 if (!objects.isEmpty()) {
110                         if (objects.get(0) instanceof UnknownObject) {
111                                 throw new PCEPDocumentedException("Unknown object encountered", ((UnknownObject) objects.get(0)).getError());
112                         }
113                         throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
114                 }
115                 return new PcrptBuilder().setPcrptMessage(new PcrptMessageBuilder().setReports(reports).build()).build();
116         }
117
118         private Reports getValidReports(final List<Object> objects) throws PCEPDocumentedException {
119                 final ReportsBuilder builder = new ReportsBuilder();
120                 if (objects.get(0) instanceof Srp) {
121                         builder.setSrp((Srp) objects.get(0));
122                         objects.remove(0);
123                 }
124                 if (objects.get(0) instanceof Lsp) {
125                         builder.setLsp((Lsp) objects.get(0));
126                         objects.remove(0);
127                 } else {
128                         throw new PCEPDocumentedException("LSP object missing", PCEPErrors.LSP_MISSING);
129                 }
130                 if (!objects.isEmpty()) {
131                         final PathBuilder pBuilder = new PathBuilder();
132                         parsePath(objects, pBuilder);
133                         builder.setPath(pBuilder.build());
134                 }
135                 return builder.build();
136         }
137
138         private void parsePath(final List<Object> objects, final PathBuilder builder) throws PCEPDocumentedException {
139                 final List<Metrics> pathMetrics = Lists.newArrayList();
140                 Object obj;
141                 State state = State.Init;
142                 while (!objects.isEmpty() && !state.equals(State.End)) {
143                         obj = objects.get(0);
144                         switch (state) {
145                         case Init:
146                                 state = State.EroIn;
147                                 if (obj instanceof Ero) {
148                                         builder.setEro((Ero) obj);
149                                         break;
150                                 }
151                         case EroIn:
152                                 state = State.LspaIn;
153                                 if (obj instanceof Lspa) {
154                                         builder.setLspa((Lspa) obj);
155                                         break;
156                                 }
157                         case LspaIn:
158                                 state = State.BandwidthIn;
159                                 if (obj instanceof Bandwidth) {
160                                         builder.setBandwidth((Bandwidth) obj);
161                                         break;
162                                 }
163                         case BandwidthIn:
164                                 state = State.MetricIn;
165                                 if (obj instanceof Metric) {
166                                         pathMetrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
167                                         state = State.BandwidthIn;
168                                         break;
169                                 }
170                         case MetricIn:
171                                 state = State.IroIn;
172                                 if (obj instanceof Iro) {
173                                         builder.setIro((Iro) obj);
174                                         break;
175                                 }
176                         case IroIn:
177                                 state = State.RroIn;
178                                 if (obj instanceof Rro) {
179                                         builder.setRro((Rro) obj);
180                                         break;
181                                 }
182                         case RroIn:
183                                 state = State.End;
184                                 break;
185                         case End:
186                                 break;
187                         default:
188                                 if (obj instanceof UnknownObject) {
189                                         throw new PCEPDocumentedException("Unknown object", ((UnknownObject) obj).getError());
190                                 }
191                         }
192                         if (!state.equals(State.End)) {
193                                 objects.remove(0);
194                         }
195                 }
196                 if (!pathMetrics.isEmpty()) {
197                         builder.setMetrics(pathMetrics);
198                 }
199         }
200
201         private enum State {
202                 Init, EroIn, LspaIn, BandwidthIn, MetricIn, IroIn, RroIn, End
203         }
204
205         @Override
206         public int getMessageType() {
207                 return TYPE;
208         }
209 }