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