256a015f314c8103a567d7afc2c83a4da8b1b29f
[bgpcep.git] / pcep / impl / src / main / java / org / opendaylight / protocol / pcep / impl / 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.impl.message;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.Lists;
13 import io.netty.buffer.ByteBuf;
14 import io.netty.buffer.Unpooled;
15 import java.util.List;
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.protocol.pcep.spi.VendorInformationObjectRegistry;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.Pcrep;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev131007.PcrepBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Message;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.Object;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.bandwidth.object.Bandwidth;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.Ero;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.include.route.object.Iro;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.attributes.Metrics;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lsp.attributes.MetricsBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.lspa.object.Lspa;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.metric.object.Metric;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.of.object.Of;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.PcrepMessageBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.Replies;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.RepliesBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.Result;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.FailureCase;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.FailureCaseBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.SuccessCase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.SuccessCaseBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.failure._case.NoPath;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.success._case.SuccessBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.success._case.success.Paths;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.pcrep.message.replies.result.success._case.success.PathsBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.rp.object.Rp;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.vendor.information.objects.VendorInformationObject;
48
49 /**
50  * Parser for {@link Pcrep}
51  */
52 public class PCEPReplyMessageParser extends AbstractMessageParser {
53
54     public static final int TYPE = 4;
55
56     public PCEPReplyMessageParser(final ObjectRegistry registry, final VendorInformationObjectRegistry viRegistry) {
57         super(registry, viRegistry);
58     }
59
60     @Override
61     public void serializeMessage(final Message message, final ByteBuf out) {
62         Preconditions.checkArgument(message instanceof Pcrep, "Wrong instance of Message. Passed instance of %s. Need Pcrep.", message.getClass());
63         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.pcrep.message.PcrepMessage repMsg = ((Pcrep) message).getPcrepMessage();
64         if (repMsg.getReplies() == null || repMsg.getReplies().isEmpty()) {
65             throw new IllegalArgumentException("Replies cannot be null or empty.");
66         }
67         final ByteBuf buffer = Unpooled.buffer();
68         for (final Replies reply : repMsg.getReplies()) {
69             if (reply.getRp() == null) {
70                 throw new IllegalArgumentException("Reply must contain RP object.");
71             }
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         serializeVendorInformationObjects(reply.getVendorInformationObject(), buffer);
80         if (reply.getResult() != null) {
81             if (reply.getResult() instanceof FailureCase) {
82                 final FailureCase f = ((FailureCase) reply.getResult());
83                 if (f != null) {
84                     serializeObject(f.getNoPath(), buffer);
85                     serializeObject(f.getLspa(), buffer);
86                     serializeObject(f.getBandwidth(), buffer);
87                     if (f.getMetrics() != null && !f.getMetrics().isEmpty()) {
88                         for (final Metrics m : f.getMetrics()) {
89                             serializeObject(m.getMetric(), buffer);
90                         }
91                     }
92                     serializeObject(f.getIro(), buffer);
93                 }
94             } else {
95                 final SuccessCase s = (SuccessCase) reply.getResult();
96                 if (s != null) {
97                     for (final Paths p : s.getSuccess().getPaths()) {
98                         serializeObject(p.getEro(), buffer);
99                         serializeObject(p.getLspa(), buffer);
100                         serializeObject(p.getOf(), buffer);
101                         serializeObject(p.getBandwidth(), buffer);
102                         if (p.getMetrics() != null && !p.getMetrics().isEmpty()) {
103                             for (final Metrics m : p.getMetrics()) {
104                                 serializeObject(m.getMetric(), buffer);
105                             }
106                         }
107                         serializeObject(p.getIro(), buffer);
108                     }
109                 }
110                 serializeVendorInformationObjects(s.getSuccess().getVendorInformationObject(), buffer);
111             }
112         }
113     }
114
115     @Override
116     protected Pcrep validate(final List<Object> objects, final List<Message> errors) throws PCEPDeserializerException {
117         if (objects == null) {
118             throw new IllegalArgumentException("Passed list can't be null.");
119         }
120         if (objects.isEmpty()) {
121             throw new PCEPDeserializerException("Pcrep message cannot be empty.");
122         }
123         final List<Replies> replies = Lists.newArrayList();
124         while (!objects.isEmpty()) {
125             final Replies r = this.getValidReply(objects, errors);
126             if (r != null) {
127                 replies.add(r);
128             }
129         }
130         if (!objects.isEmpty()) {
131             throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
132         }
133         return new PcrepBuilder().setPcrepMessage(new PcrepMessageBuilder().setReplies(replies).build()).build();
134     }
135
136     protected Replies getValidReply(final List<Object> objects, final List<Message> errors) {
137         if (!(objects.get(0) instanceof Rp)) {
138             errors.add(createErrorMsg(PCEPErrors.RP_MISSING, Optional.<Rp>absent()));
139             return null;
140         }
141         final Rp rp = (Rp) objects.get(0);
142         objects.remove(0);
143         final List<VendorInformationObject> vendorInfo = addVendorInformationObjects(objects);
144         Result res = null;
145         if (!objects.isEmpty()) {
146             if (objects.get(0) instanceof NoPath) {
147                 final NoPath noPath = (NoPath) objects.get(0);
148                 objects.remove(0);
149                 final FailureCaseBuilder builder = new FailureCaseBuilder();
150                 builder.setNoPath(noPath);
151                 while (!objects.isEmpty()) {
152                     this.parseAttributes(builder, objects);
153                 }
154                 res = builder.build();
155             } else if (objects.get(0) instanceof Ero) {
156                 final Ero ero = (Ero) objects.get(0);
157                 objects.remove(0);
158                 final SuccessBuilder builder = new SuccessBuilder();
159                 final List<Paths> paths = Lists.newArrayList();
160                 final PathsBuilder pBuilder = new PathsBuilder();
161                 pBuilder.setEro(ero);
162                 while (!objects.isEmpty()) {
163                     final List<VendorInformationObject> vendorInfoObjects = addVendorInformationObjects(objects);
164                     if (!vendorInfoObjects.isEmpty()) {
165                         builder.setVendorInformationObject(vendorInfoObjects);
166                     }
167                     this.parsePath(pBuilder, objects);
168                     paths.add(pBuilder.build());
169                 }
170                 builder.setPaths(paths);
171                 res = new SuccessCaseBuilder().setSuccess(builder.build()).build();
172             }
173         }
174         final RepliesBuilder builder = new RepliesBuilder();
175         if (!vendorInfo.isEmpty()) {
176             builder.setVendorInformationObject(vendorInfo);
177         }
178         return builder.setRp(rp).setResult(res).build();
179     }
180
181     protected void parseAttributes(final FailureCaseBuilder builder, final List<Object> objects) {
182         final List<Metrics> pathMetrics = Lists.newArrayList();
183
184         Object obj;
185         State state = State.Init;
186         while (!objects.isEmpty() && !state.equals(State.End)) {
187             obj = objects.get(0);
188
189             switch (state) {
190             case Init:
191                 state = State.LspaIn;
192                 if (obj instanceof Lspa) {
193                     builder.setLspa((Lspa) obj);
194                     break;
195                 }
196             case LspaIn:
197                 state = State.BandwidthIn;
198                 if (obj instanceof Bandwidth) {
199                     builder.setBandwidth((Bandwidth) obj);
200                     break;
201                 }
202             case BandwidthIn:
203                 state = State.MetricIn;
204                 if (obj instanceof Metric) {
205                     pathMetrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
206                     state = State.MetricIn;
207                     break;
208                 }
209             case MetricIn:
210                 state = State.IroIn;
211                 if (obj instanceof Iro) {
212                     builder.setIro((Iro) obj);
213                     break;
214                 }
215             case IroIn:
216                 state = State.End;
217                 break;
218             case End:
219                 break;
220             }
221             if (!state.equals(State.End)) {
222                 objects.remove(0);
223             }
224         }
225         if (!pathMetrics.isEmpty()) {
226             builder.setMetrics(pathMetrics);
227         }
228     }
229
230     protected void parsePath(final PathsBuilder builder, final List<Object> objects) {
231         final List<Metrics> pathMetrics = Lists.newArrayList();
232
233         Object obj;
234         State state = State.Init;
235         while (!objects.isEmpty() && !state.equals(State.End)) {
236             obj = objects.get(0);
237
238             switch (state) {
239             case Init:
240                 state = State.LspaIn;
241                 if (obj instanceof Lspa) {
242                     builder.setLspa((Lspa) obj);
243                     break;
244                 }
245             case LspaIn:
246                 state = State.OfIn;
247                 if (obj instanceof Of) {
248                     builder.setOf((Of) obj);
249                     break;
250                 }
251             case OfIn:
252                 state = State.BandwidthIn;
253                 if (obj instanceof Bandwidth) {
254                     builder.setBandwidth((Bandwidth) obj);
255                     break;
256                 }
257             case BandwidthIn:
258                 state = State.MetricIn;
259                 if (obj instanceof Metric) {
260                     pathMetrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
261                     state = State.BandwidthIn;
262                     break;
263                 }
264             case MetricIn:
265                 state = State.IroIn;
266                 if (obj instanceof Iro) {
267                     builder.setIro((Iro) obj);
268                     break;
269                 }
270             case IroIn:
271                 state = State.End;
272                 break;
273             case End:
274                 break;
275             }
276             if (!state.equals(State.End)) {
277                 objects.remove(0);
278             }
279         }
280         if (!pathMetrics.isEmpty()) {
281             builder.setMetrics(pathMetrics);
282         }
283     }
284
285     private enum State {
286         Init, LspaIn, OfIn, BandwidthIn, MetricIn, IroIn, End
287     }
288 }