Fixed various small bugs found by Findbugs plugin.
[bgpcep.git] / pcep / impl / src / main / java / org / opendaylight / protocol / pcep / impl / 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.impl.message;
9
10 import com.google.common.base.Preconditions;
11 import com.google.common.collect.Lists;
12 import io.netty.buffer.ByteBuf;
13 import io.netty.buffer.Unpooled;
14 import java.util.List;
15 import org.opendaylight.protocol.pcep.spi.AbstractMessageParser;
16 import org.opendaylight.protocol.pcep.spi.MessageUtil;
17 import org.opendaylight.protocol.pcep.spi.ObjectRegistry;
18 import org.opendaylight.protocol.pcep.spi.PCEPDeserializerException;
19 import org.opendaylight.protocol.pcep.spi.PCEPErrors;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcreq;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.PcreqBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Object;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.bandwidth.object.Bandwidth;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.classtype.object.ClassType;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.endpoints.object.EndpointsObj;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.exclude.route.object.Xro;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.gc.object.Gc;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.include.route.object.Iro;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.load.balancing.object.LoadBalancing;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.attributes.Metrics;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.attributes.MetricsBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lspa.object.Lspa;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.metric.object.Metric;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.of.object.Of;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.path.key.object.PathKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcreq.message.PcreqMessage;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcreq.message.PcreqMessageBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcreq.message.pcreq.message.Requests;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcreq.message.pcreq.message.RequestsBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcreq.message.pcreq.message.Svec;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcreq.message.pcreq.message.SvecBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcreq.message.pcreq.message.requests.PathKeyExpansionBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcreq.message.pcreq.message.requests.SegmentComputation;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcreq.message.pcreq.message.requests.SegmentComputationBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcreq.message.pcreq.message.requests.segment.computation.P2p;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcreq.message.pcreq.message.requests.segment.computation.P2pBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcreq.message.pcreq.message.requests.segment.computation.p2p.ReportedRoute;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcreq.message.pcreq.message.requests.segment.computation.p2p.ReportedRouteBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.reported.route.object.Rro;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rp.object.Rp;
52
53 /**
54  * Parser for {@link Pcreq}
55  */
56 public class PCEPRequestMessageParser extends AbstractMessageParser {
57
58     public static final int TYPE = 3;
59
60     public PCEPRequestMessageParser(final ObjectRegistry registry) {
61         super(registry);
62     }
63
64     @Override
65     public void serializeMessage(final Message message, final ByteBuf out) {
66         Preconditions.checkArgument(message instanceof Pcreq, "Wrong instance of Message. Passed instance of %s. Need Pcreq.", message.getClass());
67         final PcreqMessage msg = ((Pcreq) message).getPcreqMessage();
68         if (msg.getRequests() == null || msg.getRequests().isEmpty()) {
69             throw new IllegalArgumentException("Requests cannot be null or empty.");
70         }
71         final ByteBuf buffer = Unpooled.buffer();
72         for (final Requests req : msg.getRequests()) {
73             serializeObject(req.getRp(), buffer);
74             if (req.getPathKeyExpansion() != null) {
75                 serializeObject(req.getPathKeyExpansion().getPathKey(), buffer);
76             }
77             if (req.getSegmentComputation() != null) {
78                 final SegmentComputation sc = req.getSegmentComputation();
79                 if (sc.getP2p() != null) {
80                     serializeP2P(buffer, sc.getP2p());
81                 }
82             }
83         }
84         if (msg.getSvec() != null) {
85             for (final Svec s : msg.getSvec()) {
86                 serializeObject(s.getSvec(), buffer);
87                 if (s.getOf() != null) {
88                     serializeObject(s.getOf(), buffer);
89                 }
90                 if (s.getGc() != null) {
91                     serializeObject(s.getGc(), buffer);
92                 }
93                 if (s.getXro() != null) {
94                     serializeObject(s.getXro(), buffer);
95                 }
96                 if (s.getMetric() != null) {
97                     for (final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcreq.message.pcreq.message.svec.Metric m : s.getMetric()) {
98                         serializeObject(m.getMetric(), buffer);
99                     }
100                 }
101             }
102         }
103         MessageUtil.formatMessage(TYPE, buffer, out);
104     }
105
106     protected void serializeP2P(final ByteBuf buffer, final P2p p2p) {
107         if (p2p.getEndpointsObj() != null) {
108             serializeObject(p2p.getEndpointsObj(), buffer);
109         }
110         if (p2p.getReportedRoute() != null) {
111             final ReportedRoute rr = p2p.getReportedRoute();
112             if (rr.getRro() != null) {
113                 serializeObject(rr.getRro(), buffer);
114             }
115             if (rr.getBandwidth() != null) {
116                 serializeObject(rr.getBandwidth(), buffer);
117             }
118         }
119         if (p2p.getLoadBalancing() != null) {
120             serializeObject(p2p.getLoadBalancing(), buffer);
121         }
122         if (p2p.getLspa() != null) {
123             serializeObject(p2p.getLspa(), buffer);
124         }
125         if (p2p.getBandwidth() != null) {
126             serializeObject(p2p.getBandwidth(), buffer);
127         }
128         if (p2p.getMetrics() != null) {
129             for (final Metrics m : p2p.getMetrics()) {
130                 serializeObject(m.getMetric(), buffer);
131             }
132         }
133         if (p2p.getIro() != null) {
134             serializeObject(p2p.getIro(), buffer);
135         }
136         if (p2p.getRro() != null) {
137             serializeObject(p2p.getRro(), buffer);
138         }
139         if (p2p.getXro() != null) {
140             serializeObject(p2p.getXro(), buffer);
141         }
142         if (p2p.getOf() != null) {
143             serializeObject(p2p.getOf(), buffer);
144         }
145         if (p2p.getClassType() != null) {
146             serializeObject(p2p.getClassType(), buffer);
147         }
148     }
149
150     @Override
151     protected Message validate(
152             final List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Object> objects,
153             final List<Message> errors) throws PCEPDeserializerException {
154         if (objects == null) {
155             throw new IllegalArgumentException("Passed list can't be null.");
156         }
157
158         final List<Requests> requests = Lists.newArrayList();
159         final List<Svec> svecList = Lists.newArrayList();
160         while (!objects.isEmpty()) {
161             final RequestsBuilder rBuilder = new RequestsBuilder();
162             Rp rpObj = null;
163             if (objects.get(0) instanceof Rp) {
164                 rpObj = (Rp) objects.get(0);
165                 objects.remove(0);
166                 if (!rpObj.isProcessingRule()) {
167                     errors.add(createErrorMsg(PCEPErrors.P_FLAG_NOT_SET));
168                 } else {
169                     rBuilder.setRp(rpObj);
170                 }
171             } else {
172                 // if RP obj is missing return error only
173                 errors.add(createErrorMsg(PCEPErrors.RP_MISSING));
174                 return null;
175             }
176
177             // expansion
178             if (rpObj.isPathKey()) {
179                 if (objects.get(0) instanceof PathKey) {
180                     rBuilder.setPathKeyExpansion(new PathKeyExpansionBuilder().setPathKey((PathKey) objects.get(0)).build());
181                 }
182                 continue;
183             }
184
185             final P2pBuilder p2pBuilder = new P2pBuilder();
186
187             if (objects.get(0) instanceof EndpointsObj) {
188                 final EndpointsObj ep = (EndpointsObj) objects.get(0);
189                 objects.remove(0);
190                 if (!ep.isProcessingRule()) {
191                     errors.add(createErrorMsg(PCEPErrors.P_FLAG_NOT_SET, rpObj));
192                 } else {
193                     p2pBuilder.setEndpointsObj(ep);
194                 }
195             } else {
196                 errors.add(createErrorMsg(PCEPErrors.END_POINTS_MISSING, rpObj));
197                 return null;
198             }
199             // p2p
200             if (!rpObj.isP2mp()) {
201                 final SegmentComputation segm = getSegmentComputation(p2pBuilder, objects, errors, rpObj);
202                 if (segm != null) {
203                     rBuilder.setSegmentComputation(segm);
204                 }
205             }
206             while (!objects.isEmpty()) {
207                 final SvecBuilder sBuilder = new SvecBuilder();
208                 final Svec svecComp = getValidSvec(sBuilder, objects);
209                 if (svecComp == null) {
210                     break;
211                 }
212                 svecList.add(svecComp);
213             }
214             requests.add(rBuilder.build());
215         }
216
217         final PcreqMessageBuilder mBuilder = new PcreqMessageBuilder();
218         mBuilder.setRequests(requests);
219         if (!svecList.isEmpty()) {
220             mBuilder.setSvec(svecList);
221         }
222         return new PcreqBuilder().setPcreqMessage(mBuilder.build()).build();
223     }
224
225     protected SegmentComputation getSegmentComputation(final P2pBuilder builder, final List<Object> objects, final List<Message> errors,
226             final Rp rp) {
227         final List<Metrics> metrics = Lists.newArrayList();
228
229         State state = State.Init;
230         while (!objects.isEmpty() && state != State.End) {
231             Object obj = objects.get(0);
232
233             switch (state) {
234             case Init:
235                 state = State.ReportedIn;
236                 if (obj instanceof Rro) {
237                     final ReportedRouteBuilder rrBuilder = new ReportedRouteBuilder();
238                     rrBuilder.setRro((Rro) obj);
239                     objects.remove(0);
240                     obj = objects.get(0);
241                     if (obj instanceof Bandwidth) {
242                         rrBuilder.setBandwidth((Bandwidth) obj);
243                     }
244                     break;
245                 }
246             case ReportedIn:
247                 state = State.LoadBIn;
248                 if (obj instanceof LoadBalancing) {
249                     builder.setLoadBalancing((LoadBalancing) obj);
250                     break;
251                 }
252             case LoadBIn:
253                 state = State.LspaIn;
254                 if (obj instanceof Lspa) {
255                     builder.setLspa((Lspa) obj);
256                     break;
257                 }
258             case LspaIn:
259                 state = State.BandwidthIn;
260                 if (obj instanceof Bandwidth) {
261                     builder.setBandwidth((Bandwidth) obj);
262                     break;
263                 }
264             case BandwidthIn:
265                 state = State.MetricIn;
266                 if (obj instanceof Metric) {
267                     metrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
268                     state = State.BandwidthIn;
269                     break;
270                 }
271             case MetricIn:
272                 state = State.IroIn;
273                 if (obj instanceof Iro) {
274                     builder.setIro((Iro) obj);
275                     break;
276                 }
277             case IroIn:
278                 state = State.RroIn;
279                 if (obj instanceof Rro) {
280                     builder.setRro((Rro) obj);
281                     break;
282                 }
283             case RroIn:
284                 state = State.XroIn;
285                 if (obj instanceof Xro) {
286                     builder.setXro((Xro) obj);
287                     break;
288                 }
289             case XroIn:
290                 state = State.OfIn;
291                 if (obj instanceof Of) {
292                     builder.setOf((Of) obj);
293                     break;
294                 }
295             case OfIn:
296                 state = State.CtIn;
297                 if (obj instanceof ClassType) {
298                     final ClassType classType = (ClassType) obj;
299                     if (!classType.isProcessingRule()) {
300                         errors.add(createErrorMsg(PCEPErrors.P_FLAG_NOT_SET, rp));
301                     } else {
302                         builder.setClassType(classType);
303                     }
304                     break;
305                 }
306             case CtIn:
307                 state = State.End;
308                 break;
309             case End:
310                 break;
311             }
312             if (!state.equals(State.End)) {
313                 objects.remove(0);
314             }
315         }
316         if (!metrics.isEmpty()) {
317             builder.setMetrics(metrics);
318         }
319
320         if (rp.isReoptimization()
321                 && builder.getBandwidth() != null
322                 && builder.getReportedRoute().getBandwidth().getBandwidth() !=
323                 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth(new byte[] { 0 })
324                 && builder.getReportedRoute().getRro() == null) {
325             errors.add(createErrorMsg(PCEPErrors.RRO_MISSING, rp));
326             return null;
327         }
328         return new SegmentComputationBuilder().setP2p(builder.build()).build();
329     }
330
331     private enum State {
332         Init, ReportedIn, LoadBIn, LspaIn, BandwidthIn, MetricIn, IroIn, RroIn, XroIn, OfIn, CtIn, End
333     }
334
335     private Svec getValidSvec(final SvecBuilder builder, final List<Object> objects) {
336         if (objects == null || objects.isEmpty()) {
337             throw new IllegalArgumentException("List cannot be null or empty.");
338         }
339
340         if (objects.get(0) instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.svec.object.Svec) {
341             builder.setSvec((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.svec.object.Svec) objects.get(0));
342             objects.remove(0);
343         } else {
344             return null;
345         }
346
347         final List<Metrics> metrics = Lists.newArrayList();
348
349         Object obj = null;
350         SvecState state = SvecState.Init;
351         while (!objects.isEmpty() && !state.equals(SvecState.End)) {
352             obj = objects.get(0);
353
354             switch (state) {
355             case Init:
356                 state = SvecState.OfIn;
357                 if (obj instanceof Of) {
358                     builder.setOf((Of) obj);
359                     break;
360                 }
361             case OfIn:
362                 state = SvecState.GcIn;
363                 if (obj instanceof Gc) {
364                     builder.setGc((Gc) obj);
365                     break;
366                 }
367             case GcIn:
368                 state = SvecState.XroIn;
369                 if (obj instanceof Xro) {
370                     builder.setXro((Xro) obj);
371                     break;
372                 }
373             case XroIn:
374                 state = SvecState.MetricIn;
375                 if (obj instanceof Metric) {
376                     metrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
377                     state = SvecState.XroIn;
378                     break;
379                 }
380             case MetricIn:
381                 state = SvecState.End;
382                 break;
383             case End:
384                 break;
385             }
386             if (!state.equals(SvecState.End)) {
387                 objects.remove(0);
388             }
389         }
390         return builder.build();
391     }
392
393     private enum SvecState {
394         Init, OfIn, GcIn, XroIn, MetricIn, End
395     }
396 }