Fix checkstyle FallThrough errors
[bgpcep.git] / pcep / base-parser / src / main / java / org / opendaylight / protocol / pcep / parser / message / PCEPReplyMessageParser.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.parser.util.Util;
17 import org.opendaylight.protocol.pcep.spi.AbstractMessageParser;
18 import org.opendaylight.protocol.pcep.spi.MessageUtil;
19 import org.opendaylight.protocol.pcep.spi.ObjectRegistry;
20 import org.opendaylight.protocol.pcep.spi.PCEPDeserializerException;
21 import org.opendaylight.protocol.pcep.spi.PCEPErrors;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.Pcrep;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.PcrepBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Message;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Object;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.bandwidth.object.Bandwidth;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.Ero;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.include.route.object.Iro;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.Metrics;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.MetricsBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lspa.object.Lspa;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.metric.object.Metric;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.monitoring.metrics.MetricPce;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.monitoring.object.Monitoring;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.of.object.Of;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcc.id.req.object.PccIdReq;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pce.id.object.PceId;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.PcrepMessageBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.Replies;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.RepliesBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.Result;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.FailureCase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.FailureCaseBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.SuccessCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.SuccessCaseBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.failure._case.NoPath;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.success._case.SuccessBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.success._case.success.Paths;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.success._case.success.PathsBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.rp.object.Rp;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.vendor.information.objects.VendorInformationObject;
52
53 /**
54  * Parser for {@link Pcrep}
55  */
56 public class PCEPReplyMessageParser extends AbstractMessageParser {
57
58     public static final int TYPE = 4;
59
60     public PCEPReplyMessageParser(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 Pcrep, "Wrong instance of Message. Passed instance of %s. Need Pcrep.", message.getClass());
67         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.PcrepMessage repMsg = ((Pcrep) message).getPcrepMessage();
68         Preconditions.checkArgument(repMsg.getReplies() != null && !repMsg.getReplies().isEmpty(), "Replies cannot be null or empty.");
69         final ByteBuf buffer = Unpooled.buffer();
70         for (final Replies reply : repMsg.getReplies()) {
71             Preconditions.checkArgument(reply.getRp() != null, "Reply must contain RP object.");
72             serializeReply(reply, buffer);
73         }
74         MessageUtil.formatMessage(TYPE, buffer, out);
75     }
76
77     protected void serializeReply(final Replies reply, final ByteBuf buffer) {
78         serializeObject(reply.getRp(), buffer);
79         serializeMonitoring(reply, buffer);
80         serializeVendorInformationObjects(reply.getVendorInformationObject(), buffer);
81         if (reply.getResult() == null) {
82             return;
83         }
84         if (reply.getResult() instanceof FailureCase) {
85             final FailureCase f = (FailureCase) reply.getResult();
86             serializeFailure(f, buffer);
87             return;
88         }
89         final SuccessCase s = (SuccessCase) reply.getResult();
90         serializeSuccess(s, buffer);
91         serializeMonitoringMetrics(reply, buffer);
92     }
93
94     private void serializeFailure(final FailureCase f, final ByteBuf buffer) {
95         if (f == null) {
96             return;
97         }
98         serializeObject(f.getNoPath(), buffer);
99         serializeObject(f.getLspa(), buffer);
100         serializeObject(f.getBandwidth(), buffer);
101         if (f.getMetrics() != null) {
102             for (final Metrics m : f.getMetrics()) {
103                 serializeObject(m.getMetric(), buffer);
104             }
105         }
106         serializeObject(f.getIro(), buffer);
107     }
108
109     private void serializeSuccess(final SuccessCase s, final ByteBuf buffer) {
110         if (s == null || s.getSuccess() == null) {
111             return;
112         }
113         for (final Paths p : s.getSuccess().getPaths()) {
114             serializeObject(p.getEro(), buffer);
115             serializeObject(p.getLspa(), buffer);
116             serializeObject(p.getOf(), buffer);
117             serializeObject(p.getBandwidth(), buffer);
118             if (p.getMetrics() != null) {
119                 for (final Metrics m : p.getMetrics()) {
120                     serializeObject(m.getMetric(), buffer);
121                 }
122             }
123             serializeObject(p.getIro(), buffer);
124         }
125         serializeVendorInformationObjects(s.getSuccess().getVendorInformationObject(), buffer);
126     }
127
128     private void serializeMonitoring(final Replies reply, final ByteBuf buffer) {
129         serializeObject(reply.getMonitoring(), buffer);
130         serializeObject(reply.getPccIdReq(), buffer);
131     }
132
133     private void serializeMonitoringMetrics(final Replies reply, final ByteBuf buffer) {
134         if (reply.getMetricPce() != null) {
135             for (final MetricPce metricPce : reply.getMetricPce()) {
136                 serializeMetricPce(metricPce, buffer);
137             }
138         }
139     }
140
141     protected void serializeMetricPce(final MetricPce metricPce, final ByteBuf buffer) {
142         Preconditions.checkArgument(metricPce.getPceId() != null, "PCE-ID must be present.");
143         serializeObject(metricPce.getPceId(), buffer);
144         serializeObject(metricPce.getProcTime(), buffer);
145         serializeObject(metricPce.getOverload(), buffer);
146     }
147
148     @Override
149     protected Pcrep validate(final List<Object> objects, final List<Message> errors) throws PCEPDeserializerException {
150         Preconditions.checkArgument(objects != null, "Passed list can't be null.");
151         if (objects.isEmpty()) {
152             throw new PCEPDeserializerException("Pcrep message cannot be empty.");
153         }
154         final List<Replies> replies = new ArrayList<>();
155         while (!objects.isEmpty()) {
156             final Replies r = this.getValidReply(objects, errors);
157             if (r != null) {
158                 replies.add(r);
159             }
160         }
161         if (!objects.isEmpty()) {
162             throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
163         }
164         return new PcrepBuilder().setPcrepMessage(new PcrepMessageBuilder().setReplies(replies).build()).build();
165     }
166
167     protected Replies getValidReply(final List<Object> objects, final List<Message> errors) throws PCEPDeserializerException {
168         Object object = objects.remove(0);
169         if (!(object instanceof Rp)) {
170             errors.add(createErrorMsg(PCEPErrors.RP_MISSING, Optional.empty()));
171             return null;
172         }
173         final Rp rp = (Rp) object;
174         final RepliesBuilder repliesBuilder = new RepliesBuilder();
175         if (!objects.isEmpty() && objects.get(0) instanceof Monitoring) {
176             repliesBuilder.setMonitoring((Monitoring) objects.get(0));
177             objects.remove(0);
178         }
179         if (!objects.isEmpty() && objects.get(0) instanceof PccIdReq) {
180             repliesBuilder.setPccIdReq((PccIdReq) objects.get(0));
181             objects.remove(0);
182         }
183         final List<VendorInformationObject> vendorInfo = addVendorInformationObjects(objects);
184         Result res = null;
185         if (!objects.isEmpty()) {
186             if (objects.get(0) instanceof NoPath) {
187                 res = handleNoPath((NoPath) objects.get(0), objects);
188             } else if (objects.get(0) instanceof Ero) {
189                 res = handleEros(objects);
190             }
191         }
192         final List<MetricPce> metricPceList = new ArrayList<>();
193         if (!objects.isEmpty() && objects.get(0) instanceof PceId) {
194             while (!objects.isEmpty()) {
195                 metricPceList.add(Util.validateMonitoringMetrics(objects));
196             }
197         }
198         if (!vendorInfo.isEmpty()) {
199             repliesBuilder.setVendorInformationObject(vendorInfo);
200         }
201         if (!metricPceList.isEmpty()) {
202             repliesBuilder.setMetricPce(metricPceList);
203         }
204         return repliesBuilder.setRp(rp).setResult(res).build();
205     }
206
207     private Result handleNoPath(final NoPath noPath, final List<Object> objects) {
208         objects.remove(0);
209         final FailureCaseBuilder builder = new FailureCaseBuilder();
210         builder.setNoPath(noPath);
211         while (!objects.isEmpty() && !(objects.get(0) instanceof PceId)) {
212             this.parseAttributes(builder, objects);
213         }
214         return builder.build();
215     }
216
217     private Result handleEros(final List<Object> objects) {
218         final SuccessBuilder builder = new SuccessBuilder();
219         final List<Paths> paths = new ArrayList<>();
220         while (!objects.isEmpty() && !(objects.get(0) instanceof PceId)) {
221             final PathsBuilder pBuilder = new PathsBuilder();
222             if (objects.get(0) instanceof Ero) {
223                 pBuilder.setEro((Ero ) objects.remove(0));
224             }
225             final List<VendorInformationObject> vendorInfoObjects = addVendorInformationObjects(objects);
226             if (!vendorInfoObjects.isEmpty()) {
227                 builder.setVendorInformationObject(vendorInfoObjects);
228             }
229             this.parsePath(pBuilder, objects);
230             paths.add(pBuilder.build());
231         }
232         builder.setPaths(paths);
233         return new SuccessCaseBuilder().setSuccess(builder.build()).build();
234     }
235
236     protected void parseAttributes(final FailureCaseBuilder builder, final List<Object> objects) {
237         final List<Metrics> pathMetrics = new ArrayList<>();
238
239         Object obj;
240         State state = State.INIT;
241         while (!objects.isEmpty() && !state.equals(State.END)) {
242             obj = objects.get(0);
243             state = insertObject(state, obj, builder, pathMetrics);
244             if (!state.equals(State.END)) {
245                 objects.remove(0);
246             }
247         }
248         if (!pathMetrics.isEmpty()) {
249             builder.setMetrics(pathMetrics);
250         }
251     }
252
253     private static State insertObject(final State state, final Object obj, final FailureCaseBuilder builder,
254             final List<Metrics> pathMetrics) {
255         switch (state) {
256             case INIT:
257                 if (obj instanceof Lspa) {
258                     builder.setLspa((Lspa) obj);
259                     return State.LSPA_IN;
260                 }
261                 // fall-through
262             case LSPA_IN:
263                 if (obj instanceof Bandwidth) {
264                     builder.setBandwidth((Bandwidth) obj);
265                     return State.BANDWIDTH_IN;
266                 }
267                 // fall-through
268             case BANDWIDTH_IN:
269                 if (obj instanceof Metric) {
270                     pathMetrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
271                     return State.BANDWIDTH_IN;
272                 }
273                 // fall-through
274             case METRIC_IN:
275                 if (obj instanceof Iro) {
276                     builder.setIro((Iro) obj);
277                     return State.IRO_IN;
278                 }
279                 // fall-through
280             case IRO_IN:
281                 // fall-through
282             case END:
283                 return State.END;
284             default:
285                 return state;
286         }
287     }
288
289     protected void parsePath(final PathsBuilder builder, final List<Object> objects) {
290         final List<Metrics> pathMetrics = new ArrayList<>();
291
292         Object obj;
293         State state = State.INIT;
294         while (!objects.isEmpty() && !state.equals(State.END)) {
295             obj = objects.get(0);
296             state = insertObject(state, obj, builder, pathMetrics);
297             if (!state.equals(State.END)) {
298                 objects.remove(0);
299             }
300         }
301         if (!pathMetrics.isEmpty()) {
302             builder.setMetrics(pathMetrics);
303         }
304     }
305
306     private static State insertObject(final State state, final Object obj, final PathsBuilder builder,
307             final List<Metrics> pathMetrics) {
308         switch (state) {
309             case INIT:
310                 if (obj instanceof Lspa) {
311                     builder.setLspa((Lspa) obj);
312                     return State.LSPA_IN;
313                 }
314                 // fall-through
315             case LSPA_IN:
316                 if (obj instanceof Of) {
317                     builder.setOf((Of) obj);
318                     return State.OF_IN;
319                 }
320                 // fall-through
321             case OF_IN:
322                 if (obj instanceof Bandwidth) {
323                     builder.setBandwidth((Bandwidth) obj);
324                     return State.BANDWIDTH_IN;
325                 }
326                 // fall-through
327             case BANDWIDTH_IN:
328                 if (obj instanceof Metric) {
329                     pathMetrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
330                     return State.BANDWIDTH_IN;
331                 }
332                 // fall-through
333             case METRIC_IN:
334                 if (obj instanceof Iro) {
335                     builder.setIro((Iro) obj);
336                     return State.IRO_IN;
337                 }
338                 // fall-through
339             case IRO_IN:
340                 // fall-through
341             case END:
342                 return State.END;
343             default:
344                 return state;
345         }
346     }
347
348     private enum State {
349         INIT, LSPA_IN, OF_IN, BANDWIDTH_IN, METRIC_IN, IRO_IN, END
350     }
351 }