1dbbc65b7030e42b4a8a2aee37adc49a503f7007
[bgpcep.git] / pcep / base-parser / src / main / java / org / opendaylight / protocol / pcep / parser / message / PCEPRequestMessageParser.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.parser.message;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11
12 import com.google.common.base.Preconditions;
13 import io.netty.buffer.ByteBuf;
14 import io.netty.buffer.Unpooled;
15 import java.util.ArrayList;
16 import java.util.List;
17 import java.util.Optional;
18 import java.util.Queue;
19 import org.opendaylight.protocol.pcep.spi.AbstractMessageParser;
20 import org.opendaylight.protocol.pcep.spi.MessageUtil;
21 import org.opendaylight.protocol.pcep.spi.ObjectRegistry;
22 import org.opendaylight.protocol.pcep.spi.PCEPDeserializerException;
23 import org.opendaylight.protocol.pcep.spi.PCEPErrors;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.Pcreq;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.PcreqBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Message;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Object;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.bandwidth.object.Bandwidth;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.bnc.object.BranchNodeType;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.bnc.object.branch.node.type.BranchNodeCase;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.bnc.object.branch.node.type.BranchNodeCaseBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.bnc.object.branch.node.type.NonBranchNodeCase;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.bnc.object.branch.node.type.NonBranchNodeCaseBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.branch.node.object.BranchNodeList;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.classtype.object.ClassType;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.object.EndpointsObj;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.exclude.route.object.Xro;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.gc.object.Gc;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.include.route.object.Iro;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.load.balancing.object.LoadBalancing;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.Metrics;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.MetricsBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lspa.object.Lspa;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.metric.object.Metric;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.monitoring.object.Monitoring;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.non.branch.node.object.NonBranchNodeList;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.of.object.Of;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.path.key.object.PathKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcc.id.req.object.PccIdReq;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pce.id.object.PceId;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.PcreqMessage;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.PcreqMessageBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.MonitoringRequest;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.MonitoringRequestBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.Requests;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.RequestsBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.Svec;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.SvecBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.monitoring.request.PceIdList;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.monitoring.request.PceIdListBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.PathKeyExpansionBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.SegmentComputation;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.SegmentComputationBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.P2mp;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.P2mpBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.P2p;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.P2pBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.p2mp.EndpointRroPair;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.p2mp.EndpointRroPairBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.p2mp.MetricBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.p2mp.endpoint.rro.pair.Rros;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.p2mp.endpoint.rro.pair.RrosBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.p2mp.endpoint.rro.pair.rros.route.object.ReportedRouteObjectCase;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.p2mp.endpoint.rro.pair.rros.route.object.ReportedRouteObjectCaseBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.p2mp.endpoint.rro.pair.rros.route.object.SecondaryReportedRouteObjectCase;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.p2mp.endpoint.rro.pair.rros.route.object.SecondaryReportedRouteObjectCaseBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.p2mp.iro.bnc.choice.BncCase;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.p2mp.iro.bnc.choice.BncCaseBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.p2mp.iro.bnc.choice.IroCase;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.p2mp.iro.bnc.choice.IroCaseBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.p2p.ReportedRoute;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.reoptimization.bandwidth.object.ReoptimizationBandwidth;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.reported.route.object.Rro;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.rp.object.Rp;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.secondary.reported.route.object.Srro;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.vendor.information.objects.VendorInformationObject;
87
88 /**
89  * Parser for {@link Pcreq}.
90  */
91 public class PCEPRequestMessageParser extends AbstractMessageParser {
92
93     public static final int TYPE = 3;
94
95     public PCEPRequestMessageParser(final ObjectRegistry registry) {
96         super(registry);
97     }
98
99     @Override
100     public void serializeMessage(final Message message, final ByteBuf out) {
101         checkArgument(message instanceof Pcreq,
102                 "Wrong instance of Message. Passed instance of %s. Need Pcreq.", message.getClass());
103         final PcreqMessage msg = ((Pcreq) message).getPcreqMessage();
104         checkArgument(!msg.nonnullRequests().isEmpty(), "Requests cannot be null or empty.");
105         final ByteBuf buffer = Unpooled.buffer();
106         if (msg.getMonitoringRequest() != null) {
107             serializeMonitoringRequest(msg.getMonitoringRequest(), buffer);
108         }
109         if (msg.getSvec() != null) {
110             serializeSvec(msg, buffer);
111         }
112         serializeRequest(msg, buffer);
113         MessageUtil.formatMessage(TYPE, buffer, out);
114     }
115
116     protected void serializeRequest(final PcreqMessage msg, final ByteBuf buffer) {
117         for (final Requests req : msg.nonnullRequests()) {
118             serializeObject(req.getRp(), buffer);
119             serializeVendorInformationObjects(req.getVendorInformationObject(), buffer);
120             if (req.getPathKeyExpansion() != null) {
121                 serializeObject(req.getPathKeyExpansion().getPathKey(), buffer);
122             }
123             if (req.getSegmentComputation() != null) {
124                 final SegmentComputation sc = req.getSegmentComputation();
125                 if (sc.getP2p() != null) {
126                     serializeP2P(buffer, sc.getP2p());
127                 }
128                 if (sc.getP2mp() != null) {
129                     serializeP2MP(buffer, sc.getP2mp());
130                 }
131             }
132         }
133     }
134
135     protected void serializeSvec(final PcreqMessage msg, final ByteBuf buffer) {
136         for (final Svec s : msg.nonnullSvec()) {
137             serializeObject(s.getSvec(), buffer);
138             serializeObject(s.getOf(), buffer);
139             serializeObject(s.getGc(), buffer);
140             serializeObject(s.getXro(), buffer);
141             if (s.getMetric() != null) {
142                 for (final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq
143                         .message.pcreq.message.svec.Metric m : s.nonnullMetric()) {
144                     serializeObject(m.getMetric(), buffer);
145                 }
146             }
147             serializeVendorInformationObjects(s.getVendorInformationObject(), buffer);
148         }
149     }
150
151     protected void serializeP2P(final ByteBuf buffer, final P2p p2p) {
152         serializeObject(p2p.getEndpointsObj(), buffer);
153         serializeVendorInformationObjects(p2p.getVendorInformationObject(), buffer);
154         if (p2p.getReportedRoute() != null) {
155             final ReportedRoute rr = p2p.getReportedRoute();
156             if (rr != null) {
157                 serializeObject(rr.getRro(), buffer);
158                 serializeObject(rr.getReoptimizationBandwidth(), buffer);
159             }
160         }
161         serializeObject(p2p.getLoadBalancing(), buffer);
162         serializeObject(p2p.getLspa(), buffer);
163         serializeObject(p2p.getBandwidth(), buffer);
164         for (final Metrics m : p2p.nonnullMetrics()) {
165             serializeObject(m.getMetric(), buffer);
166         }
167         serializeObject(p2p.getIro(), buffer);
168         serializeObject(p2p.getRro(), buffer);
169         serializeObject(p2p.getXro(), buffer);
170         serializeObject(p2p.getOf(), buffer);
171         serializeObject(p2p.getClassType(), buffer);
172     }
173
174     protected void serializeP2MP(final ByteBuf buffer, final P2mp p2mp) {
175         final List<EndpointRroPair> endpointRroPairList = p2mp.getEndpointRroPair();
176         if (endpointRroPairList == null || endpointRroPairList.isEmpty()) {
177             throw new IllegalStateException("At least one instance of Endpoint must be present in P2MP Request!");
178         }
179         endpointRroPairList.forEach(pair -> {
180             serializeObject(pair.getEndpointsObj(), buffer);
181             pair.nonnullRros().forEach(rro -> {
182                 if (rro.getRouteObject() instanceof ReportedRouteObjectCase) {
183                     serializeObject(((ReportedRouteObjectCase) rro.getRouteObject()).getRro(), buffer);
184                 } else if (rro.getRouteObject() instanceof SecondaryReportedRouteObjectCase) {
185                     serializeObject(((SecondaryReportedRouteObjectCase) rro.getRouteObject()).getSrro(), buffer);
186                 }
187             });
188             serializeObject(pair.getReoptimizationBandwidth(), buffer);
189         });
190         serializeObject(p2mp.getOf(), buffer);
191         serializeObject(p2mp.getLspa(), buffer);
192         serializeObject(p2mp.getBandwidth(), buffer);
193         for (final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq
194                 .message.pcreq.message.requests.segment.computation.p2mp.Metric m : p2mp.nonnullMetric()) {
195             serializeObject(m.getMetric(), buffer);
196         }
197         if (p2mp.getIroBncChoice() instanceof IroCase) {
198             serializeObject(((IroCase) p2mp.getIroBncChoice()).getIro(), buffer);
199         } else if (p2mp.getIroBncChoice() instanceof BncCase) {
200             final BranchNodeType branchNodeType = ((BncCase) p2mp.getIroBncChoice()).getBranchNodeType();
201             if (branchNodeType instanceof BranchNodeCase) {
202                 serializeObject(((BranchNodeCase) branchNodeType).getBranchNodeList(), buffer);
203             } else if (branchNodeType instanceof NonBranchNodeCase) {
204                 serializeObject(((NonBranchNodeCase) branchNodeType).getNonBranchNodeList(), buffer);
205             }
206         }
207         serializeObject(p2mp.getLoadBalancing(), buffer);
208     }
209
210     protected void serializeMonitoringRequest(final MonitoringRequest monReq, final ByteBuf out) {
211         serializeObject(monReq.getMonitoring(), out);
212         serializeObject(monReq.getPccIdReq(), out);
213         for (final PceIdList pceId : monReq.nonnullPceIdList()) {
214             serializeObject(pceId.getPceId(), out);
215         }
216     }
217
218     @Override
219     protected Message validate(final Queue<Object> objects, final List<Message> errors)
220             throws PCEPDeserializerException {
221         Preconditions.checkArgument(objects != null, "Passed list can't be null.");
222         if (objects.isEmpty()) {
223             throw new PCEPDeserializerException("Pcrep message cannot be empty.");
224         }
225         final PcreqMessageBuilder mBuilder = new PcreqMessageBuilder().setMonitoringRequest(getMonitoring(objects));
226         final List<Svec> svecs = getSvecs(objects);
227         if (!svecs.isEmpty()) {
228             mBuilder.setSvec(svecs);
229         }
230         final List<Requests> requests = getRequests(objects, errors);
231         if (requests != null) {
232             mBuilder.setRequests(requests);
233         } else {
234             errors.add(createErrorMsg(PCEPErrors.RP_MISSING, Optional.empty()));
235         }
236         if (!objects.isEmpty()) {
237             throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
238         }
239         return new PcreqBuilder().setPcreqMessage(mBuilder.build()).build();
240     }
241
242     protected List<Svec> getSvecs(final Queue<Object> objects) {
243         final List<Svec> svecList = new ArrayList<>();
244         while (!objects.isEmpty()) {
245             final SvecBuilder sBuilder = new SvecBuilder();
246             final Svec svecComp = getValidSvec(sBuilder, objects);
247             if (svecComp == null) {
248                 break;
249             }
250             svecList.add(svecComp);
251         }
252         return svecList;
253     }
254
255     protected List<Requests> getRequests(final Queue<Object> objects, final List<Message> errors) {
256         final List<Requests> requests = new ArrayList<>();
257
258         for (Object obj = objects.peek(); obj != null; obj = objects.peek()) {
259             if (!(obj instanceof Rp)) {
260                 // if RP obj is missing return error only
261                 errors.add(createErrorMsg(PCEPErrors.RP_MISSING, Optional.empty()));
262                 return null;
263             }
264
265             final RequestsBuilder rBuilder = new RequestsBuilder();
266             final Rp rpObj = (Rp) obj;
267             objects.remove();
268
269             if (rpObj.getProcessingRule()) {
270                 rBuilder.setRp(rpObj);
271             } else {
272                 errors.add(createErrorMsg(PCEPErrors.P_FLAG_NOT_SET, Optional.empty()));
273             }
274
275             final List<VendorInformationObject> vendorInfo = addVendorInformationObjects(objects);
276             if (!vendorInfo.isEmpty()) {
277                 rBuilder.setVendorInformationObject(vendorInfo);
278             }
279
280             // expansion
281             if (rpObj.getPathKey()) {
282                 // FIXME: this can fail on malformed messages (i.e. objects.isEmpty()), add an explicit check/error
283                 obj = objects.element();
284                 if (obj instanceof PathKey) {
285                     // FIXME: shouldn't we be also removing the object?
286                     rBuilder.setPathKeyExpansion(new PathKeyExpansionBuilder().setPathKey((PathKey) obj).build());
287                 }
288             }
289
290             obj = objects.peek();
291             if (!(obj instanceof EndpointsObj)) {
292                 errors.add(createErrorMsg(PCEPErrors.END_POINTS_MISSING, Optional.of(rpObj)));
293                 return null;
294             }
295
296             if (!rpObj.getP2mp()) {
297                 // p2p
298                 // FIXME: explicit check for empty/type?
299                 final EndpointsObj ep = (EndpointsObj) objects.remove();
300
301                 final P2pBuilder p2pBuilder = new P2pBuilder();
302                 if (!ep.getProcessingRule()) {
303                     errors.add(createErrorMsg(PCEPErrors.P_FLAG_NOT_SET, Optional.of(rpObj)));
304                 } else {
305                     p2pBuilder.setEndpointsObj(ep);
306                 }
307
308                 final SegmentComputation segm = getP2PSegmentComputation(p2pBuilder, objects, errors, rpObj);
309                 if (segm != null) {
310                     rBuilder.setSegmentComputation(segm);
311                 }
312             } else {
313                 // p2mp
314                 final SegmentComputation segm = getP2MPSegmentComputation(objects, errors, rpObj);
315                 if (segm != null) {
316                     rBuilder.setSegmentComputation(segm);
317                 }
318             }
319             requests.add(rBuilder.build());
320         }
321         return requests;
322     }
323
324     protected SegmentComputation getP2PSegmentComputation(final P2pBuilder builder,
325                                                           final Queue<Object> objects,
326                                                           final List<Message> errors,
327                                                           final Rp rp) {
328         final List<Metrics> metrics = new ArrayList<>();
329         final List<VendorInformationObject> viObjects = new ArrayList<>();
330
331         P2PState p2PState = P2PState.INIT;
332         while (!objects.isEmpty() && p2PState != P2PState.END) {
333             p2PState = insertP2PObject(p2PState, objects, viObjects, builder, metrics, errors, rp);
334             if (!p2PState.equals(P2PState.END)) {
335                 objects.remove();
336             }
337         }
338         if (!metrics.isEmpty()) {
339             builder.setMetrics(metrics);
340         }
341         if (!viObjects.isEmpty()) {
342             builder.setVendorInformationObject(viObjects);
343         }
344
345         if (rp.getReoptimization() && builder.getBandwidth() != null
346                 && !builder.getReportedRoute().getReoptimizationBandwidth().getBandwidth().equals(
347                         new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network
348                             .concepts.rev131125.Bandwidth(new byte[] { 0 }))
349                 && builder.getReportedRoute().getRro() == null) {
350             errors.add(createErrorMsg(PCEPErrors.RRO_MISSING, Optional.of(rp)));
351             return null;
352         }
353         return new SegmentComputationBuilder().setP2p(builder.build()).build();
354     }
355
356     // Note: objects is expected to be non-empty and caller will remove the first object if non-empty
357     private static P2PState insertP2PObject(final P2PState p2PState,
358                                             final Queue<Object> objects,
359                                             final List<VendorInformationObject> viObjects,
360                                             final P2pBuilder builder,
361                                             final List<Metrics> metrics,
362                                             final List<Message> errors,
363                                             final Rp rp) {
364         final Object obj = objects.element();
365         switch (p2PState) {
366             case INIT:
367                 if (obj instanceof Rro) {
368                     builder.setRro((Rro) obj);
369                     objects.remove();
370
371                     // FIXME: should we guard against empty objects?
372                     final Object nextObj = objects.element();
373                     if (nextObj instanceof ReoptimizationBandwidth) {
374                         builder.setReoptimizationBandwidth((ReoptimizationBandwidth) nextObj);
375                     }
376                     return P2PState.REPORTED_IN;
377                 }
378                 // fallthrough
379             case REPORTED_IN:
380                 if (obj instanceof VendorInformationObject) {
381                     viObjects.add((VendorInformationObject) obj);
382                     return P2PState.REPORTED_IN;
383                 }
384                 // fallthrough
385             case VENDOR_INFO_LIST:
386                 if (obj instanceof LoadBalancing) {
387                     builder.setLoadBalancing((LoadBalancing) obj);
388                     return P2PState.LOAD_BIN;
389                 }
390                 // fallthrough
391             case LOAD_BIN:
392                 if (obj instanceof Lspa) {
393                     builder.setLspa((Lspa) obj);
394                     return P2PState.LSPA_IN;
395                 }
396                 // fallthrough
397             case LSPA_IN:
398                 if (obj instanceof Bandwidth) {
399                     builder.setBandwidth((Bandwidth) obj);
400                     return P2PState.BANDWIDTH_IN;
401                 }
402                 // fallthrough
403             case BANDWIDTH_IN:
404                 if (obj instanceof Metric) {
405                     metrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
406                     return P2PState.BANDWIDTH_IN;
407                 }
408                 // fallthrough
409             case METRIC_IN:
410                 if (obj instanceof Iro) {
411                     builder.setIro((Iro) obj);
412                     return P2PState.IRO_IN;
413                 }
414                 // fallthrough
415             case IRO_IN:
416                 if (obj instanceof Rro) {
417                     builder.setRro((Rro) obj);
418                     return P2PState.RRO_IN;
419                 }
420                 // fallthrough
421             case RRO_IN:
422                 if (obj instanceof Xro) {
423                     builder.setXro((Xro) obj);
424                     return P2PState.XRO_IN;
425                 }
426                 // fallthrough
427             case XRO_IN:
428                 if (obj instanceof Of) {
429                     builder.setOf((Of) obj);
430                     return P2PState.OF_IN;
431                 }
432                 // fallthrough
433             case OF_IN:
434                 if (obj instanceof ClassType) {
435                     final ClassType classType = (ClassType) obj;
436                     if (!classType.getProcessingRule()) {
437                         errors.add(createErrorMsg(PCEPErrors.P_FLAG_NOT_SET, Optional.of(rp)));
438                     } else {
439                         builder.setClassType(classType);
440                     }
441                     return P2PState.CT_IN;
442                 }
443                 // fallthrough
444             case CT_IN:
445             case END:
446                 return P2PState.END;
447             default:
448                 return p2PState;
449         }
450     }
451
452     private static SvecState insertP2PObject(final SvecState state, final Object obj, final SvecBuilder builder,
453             final List<Metrics> metrics, final List<VendorInformationObject> viObjects) {
454         switch (state) {
455             case INIT:
456                 if (obj instanceof Of) {
457                     builder.setOf((Of) obj);
458                     return SvecState.OF_IN;
459                 }
460                 // fallthrough
461             case OF_IN:
462                 if (obj instanceof Gc) {
463                     builder.setGc((Gc) obj);
464                     return SvecState.GC_IN;
465                 }
466                 // fallthrough
467             case GC_IN:
468                 if (obj instanceof Xro) {
469                     builder.setXro((Xro) obj);
470                     return SvecState.XRO_IN;
471                 }
472                 // fallthrough
473             case XRO_IN:
474                 if (obj instanceof Metric) {
475                     metrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
476                     return SvecState.XRO_IN;
477                 }
478                 // fallthrough
479             case METRIC_IN:
480                 if (obj instanceof VendorInformationObject) {
481                     viObjects.add((VendorInformationObject) obj);
482                     return SvecState.METRIC_IN;
483                 }
484                 // fallthrough
485             case VENDOR_INFO:
486             case END:
487                 return SvecState.END;
488             default:
489                 return state;
490         }
491     }
492
493     private enum P2PState {
494         INIT,
495         REPORTED_IN,
496         VENDOR_INFO_LIST,
497         LOAD_BIN, LSPA_IN,
498         BANDWIDTH_IN,
499         METRIC_IN,
500         IRO_IN,
501         RRO_IN,
502         XRO_IN,
503         OF_IN,
504         CT_IN,
505         END
506     }
507
508     protected SegmentComputation getP2MPSegmentComputation(final Queue<Object> objects, final List<Message> errors,
509             final Rp rp) {
510         final List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message
511             .pcreq.message.requests.segment.computation.p2mp.Metric> metrics = new ArrayList<>();
512         final P2mpBuilder builder = new P2mpBuilder();
513         final List<EndpointRroPair> epRros = new ArrayList<>();
514
515         P2MPState state = P2MPState.RP;
516         while (!objects.isEmpty() && state != P2MPState.END) {
517             state = insertP2MPObject(state, objects, builder, epRros, metrics, errors, rp);
518             if (!state.equals(P2MPState.END)) {
519                 objects.remove();
520             }
521         }
522         if (!epRros.isEmpty()) {
523             builder.setEndpointRroPair(epRros);
524         }
525         if (!metrics.isEmpty()) {
526             builder.setMetric(metrics);
527         }
528
529         if (rp.getReoptimization() && builder.getBandwidth() != null) {
530             if (!isValidReoptimizationRro(epRros) || !isValidReoptimizationBandwidth(epRros)) {
531                 errors.add(createErrorMsg(PCEPErrors.RRO_MISSING, Optional.of(rp)));
532             }
533         }
534
535         return new SegmentComputationBuilder().setP2mp(builder.build()).build();
536     }
537
538     private static boolean isValidReoptimizationRro(final List<EndpointRroPair> epRros) {
539         for (EndpointRroPair epRro : epRros) {
540             if (epRro.nonnullRros().isEmpty()) {
541                 return false;
542             }
543         }
544         return true;
545     }
546
547     private static boolean isValidReoptimizationBandwidth(final List<EndpointRroPair> epRros) {
548         for (EndpointRroPair epRro : epRros) {
549             if (epRro.getReoptimizationBandwidth() == null) {
550                 return false;
551             }
552         }
553         return true;
554     }
555
556     private static P2MPState insertP2MPObject(final P2MPState p2MPState, final Queue<Object> objects,
557             final P2mpBuilder builder, final List<EndpointRroPair> epRros,
558             final List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq
559                 .message.pcreq.message.requests.segment.computation.p2mp.Metric> metrics,
560             final List<Message> errors, final Rp rp) {
561         final Object obj = objects.element();
562         switch (p2MPState) {
563             case RP:
564                 if (obj instanceof EndpointsObj) {
565                     final EndpointRroPairBuilder rroPairBuilder = new EndpointRroPairBuilder();
566                     if (obj.getProcessingRule()) {
567                         rroPairBuilder.setEndpointsObj((EndpointsObj) obj);
568                     } else {
569                         errors.add(createErrorMsg(PCEPErrors.P_FLAG_NOT_SET, Optional.of(rp)));
570                     }
571                     epRros.add(rroPairBuilder.setRros(new ArrayList<>()).build());
572                     return P2MPState.ENDPOINT;
573                 }
574                 // fallthrough
575             case ENDPOINT:
576                 if (obj instanceof Rro || obj instanceof Srro) {
577                     if (obj.getProcessingRule()) {
578                         final int lastIndex = epRros.size() - 1;
579                         final EndpointRroPair endpointRroPair = epRros.get(lastIndex);
580                         List<Rros> rros = endpointRroPair.getRros();
581                         if (rros == null) {
582                             rros = new ArrayList<>();
583                         }
584                         if (obj instanceof Rro) {
585                             rros.add(new RrosBuilder()
586                                     .setRouteObject(new ReportedRouteObjectCaseBuilder().setRro((Rro) obj)
587                                             .build()).build());
588                         } else {
589                             rros.add(new RrosBuilder()
590                                     .setRouteObject(new SecondaryReportedRouteObjectCaseBuilder().setSrro((Srro) obj)
591                                             .build()).build());
592                         }
593                         epRros.remove(lastIndex);
594                         epRros.add(lastIndex, new EndpointRroPairBuilder(endpointRroPair).setRros(rros).build());
595                     }
596                     return P2MPState.ENDPOINT;
597                 }
598                 // fallthrough
599             case RRO_SRRO:
600                 if (obj instanceof ReoptimizationBandwidth) {
601                     final int lastIndex = epRros.size() - 1;
602                     final EndpointRroPair endpointRroPair = epRros.get(lastIndex);
603                     epRros.remove(lastIndex);
604                     epRros.add(lastIndex, new EndpointRroPairBuilder(endpointRroPair)
605                             .setReoptimizationBandwidth((ReoptimizationBandwidth) obj)
606                             .build());
607                     return P2MPState.BANDWIDTH;
608                 }
609                 // fallthrough
610             case BANDWIDTH:
611                 if (obj instanceof EndpointsObj) {
612                     return P2MPState.RP;
613                 }
614                 if (obj instanceof Of) {
615                     builder.setOf((Of) obj);
616                     return P2MPState.OF_IN;
617                 }
618                 // fallthrough
619             case OF_IN:
620                 if (obj instanceof Lspa) {
621                     builder.setLspa((Lspa) obj);
622                     return P2MPState.LSPA_IN;
623                 }
624                 // fallthrough
625             case LSPA_IN:
626                 if (obj instanceof Bandwidth) {
627                     builder.setBandwidth((Bandwidth) obj);
628                     return P2MPState.BANDWIDTH_IN;
629                 }
630                 // fallthrough
631             case BANDWIDTH_IN:
632                 if (obj instanceof Metric) {
633                     metrics.add(new MetricBuilder().setMetric((Metric) obj).build());
634                     return P2MPState.BANDWIDTH_IN;
635                 }
636                 // fallthrough
637             case METRIC_IN:
638                 if (obj instanceof Iro) {
639                     builder.setIroBncChoice(new IroCaseBuilder().setIro((Iro) obj).build());
640                     return P2MPState.IRO_BNC_IN;
641                 }
642                 if (obj instanceof BranchNodeList) {
643                     builder.setIroBncChoice(new BncCaseBuilder().setBranchNodeType(new BranchNodeCaseBuilder()
644                             .setBranchNodeList((BranchNodeList) obj).build()).build());
645                     return P2MPState.IRO_BNC_IN;
646                 }
647                 if (obj instanceof NonBranchNodeList) {
648                     builder.setIroBncChoice(new BncCaseBuilder().setBranchNodeType(new NonBranchNodeCaseBuilder()
649                             .setNonBranchNodeList((NonBranchNodeList) obj).build()).build());
650                     return P2MPState.IRO_BNC_IN;
651                 }
652                 // fallthrough
653             case IRO_BNC_IN:
654                 if (obj instanceof LoadBalancing) {
655                     builder.setLoadBalancing((LoadBalancing) obj);
656                     return P2MPState.LOAD_BIN;
657                 }
658                 // fallthrough
659             case LOAD_BIN:
660             case END:
661             default:
662                 return P2MPState.END;
663         }
664     }
665
666     private enum P2MPState {
667         RP, ENDPOINT, RRO_SRRO, BANDWIDTH, OF_IN, LSPA_IN, BANDWIDTH_IN, METRIC_IN, IRO_BNC_IN, LOAD_BIN, END
668     }
669
670     // Note: objects is expected to be non-empty
671     private static Svec getValidSvec(final SvecBuilder builder, final Queue<Object> objects) {
672         final Object svec = objects.element();
673         if (svec instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.svec
674                 .object.Svec) {
675             builder.setSvec((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.svec
676                 .object.Svec) svec);
677             objects.remove();
678         } else {
679             return null;
680         }
681
682         // FIXME: this list is not retained anywhere
683         final List<Metrics> metrics = new ArrayList<>();
684         final List<VendorInformationObject> viObjects = new ArrayList<>();
685
686         SvecState state = SvecState.INIT;
687         for (Object obj = objects.peek(); obj != null; obj = objects.peek()) {
688             state = insertP2PObject(state, obj, builder, metrics, viObjects);
689             if (state == SvecState.END) {
690                 break;
691             }
692
693             objects.remove();
694         }
695
696         if (!viObjects.isEmpty()) {
697             builder.setVendorInformationObject(viObjects);
698         }
699         return builder.build();
700     }
701
702     private enum SvecState {
703         INIT, OF_IN, GC_IN, XRO_IN, METRIC_IN, VENDOR_INFO, END
704     }
705
706     protected MonitoringRequest getMonitoring(final Queue<Object> objects) {
707         final MonitoringRequestBuilder builder = new MonitoringRequestBuilder();
708
709         Object obj = objects.peek();
710         if (obj instanceof Monitoring) {
711             builder.setMonitoring((Monitoring) obj);
712             objects.remove();
713         } else {
714             return null;
715         }
716
717         obj = objects.peek();
718         if (obj instanceof PccIdReq) {
719             builder.setPccIdReq((PccIdReq) obj);
720             objects.remove();
721             obj = objects.peek();
722         }
723
724         final List<PceIdList> pceIdList = new ArrayList<>();
725         while (obj instanceof PceId) {
726             pceIdList.add(new PceIdListBuilder().setPceId((PceId) obj).build());
727             objects.remove();
728             obj = objects.peek();
729         }
730
731         if (!pceIdList.isEmpty()) {
732             builder.setPceIdList(pceIdList);
733         }
734         return builder.build();
735     }
736 }