6ef825c4e448c56c05c39f1144819a6ff64398f6
[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 io.netty.buffer.ByteBuf;
13 import io.netty.buffer.Unpooled;
14 import java.util.ArrayList;
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             return;
82         }
83         if (reply.getResult() instanceof FailureCase) {
84             final FailureCase f = ((FailureCase) reply.getResult());
85             if (f != null) {
86                 serializeObject(f.getNoPath(), buffer);
87                 serializeObject(f.getLspa(), buffer);
88                 serializeObject(f.getBandwidth(), buffer);
89                 if (f.getMetrics() != null) {
90                     for (final Metrics m : f.getMetrics()) {
91                         serializeObject(m.getMetric(), buffer);
92                     }
93                 }
94                 serializeObject(f.getIro(), buffer);
95             }
96             return;
97         }
98         final SuccessCase s = (SuccessCase) reply.getResult();
99         if (s != null && s.getSuccess() != null) {
100             for (final Paths p : s.getSuccess().getPaths()) {
101                 serializeObject(p.getEro(), buffer);
102                 serializeObject(p.getLspa(), buffer);
103                 serializeObject(p.getOf(), buffer);
104                 serializeObject(p.getBandwidth(), buffer);
105                 if (p.getMetrics() != null) {
106                     for (final Metrics m : p.getMetrics()) {
107                         serializeObject(m.getMetric(), buffer);
108                     }
109                 }
110                 serializeObject(p.getIro(), buffer);
111             }
112             serializeVendorInformationObjects(s.getSuccess().getVendorInformationObject(), buffer);
113         }
114     }
115
116     @Override
117     protected Pcrep validate(final List<Object> objects, final List<Message> errors) throws PCEPDeserializerException {
118         if (objects == null) {
119             throw new IllegalArgumentException("Passed list can't be null.");
120         }
121         if (objects.isEmpty()) {
122             throw new PCEPDeserializerException("Pcrep message cannot be empty.");
123         }
124         final List<Replies> replies = new ArrayList<>();
125         while (!objects.isEmpty()) {
126             final Replies r = this.getValidReply(objects, errors);
127             if (r != null) {
128                 replies.add(r);
129             }
130         }
131         if (!objects.isEmpty()) {
132             throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
133         }
134         return new PcrepBuilder().setPcrepMessage(new PcrepMessageBuilder().setReplies(replies).build()).build();
135     }
136
137     protected Replies getValidReply(final List<Object> objects, final List<Message> errors) {
138         if (!(objects.get(0) instanceof Rp)) {
139             errors.add(createErrorMsg(PCEPErrors.RP_MISSING, Optional.<Rp>absent()));
140             return null;
141         }
142         final Rp rp = (Rp) objects.get(0);
143         objects.remove(0);
144         final List<VendorInformationObject> vendorInfo = addVendorInformationObjects(objects);
145         Result res = null;
146         if (!objects.isEmpty()) {
147             if (objects.get(0) instanceof NoPath) {
148                 final NoPath noPath = (NoPath) objects.get(0);
149                 objects.remove(0);
150                 final FailureCaseBuilder builder = new FailureCaseBuilder();
151                 builder.setNoPath(noPath);
152                 while (!objects.isEmpty()) {
153                     this.parseAttributes(builder, objects);
154                 }
155                 res = builder.build();
156             } else if (objects.get(0) instanceof Ero) {
157                 final Ero ero = (Ero) objects.get(0);
158                 objects.remove(0);
159                 final SuccessBuilder builder = new SuccessBuilder();
160                 final List<Paths> paths = new ArrayList<>();
161                 final PathsBuilder pBuilder = new PathsBuilder();
162                 pBuilder.setEro(ero);
163                 while (!objects.isEmpty()) {
164                     final List<VendorInformationObject> vendorInfoObjects = addVendorInformationObjects(objects);
165                     if (!vendorInfoObjects.isEmpty()) {
166                         builder.setVendorInformationObject(vendorInfoObjects);
167                     }
168                     this.parsePath(pBuilder, objects);
169                     paths.add(pBuilder.build());
170                 }
171                 builder.setPaths(paths);
172                 res = new SuccessCaseBuilder().setSuccess(builder.build()).build();
173             }
174         }
175         final RepliesBuilder builder = new RepliesBuilder();
176         if (!vendorInfo.isEmpty()) {
177             builder.setVendorInformationObject(vendorInfo);
178         }
179         return builder.setRp(rp).setResult(res).build();
180     }
181
182     protected void parseAttributes(final FailureCaseBuilder builder, final List<Object> objects) {
183         final List<Metrics> pathMetrics = new ArrayList<>();
184
185         Object obj;
186         State state = State.INIT;
187         while (!objects.isEmpty() && !state.equals(State.END)) {
188             obj = objects.get(0);
189
190             switch (state) {
191             case INIT:
192                 state = State.LSPA_IN;
193                 if (obj instanceof Lspa) {
194                     builder.setLspa((Lspa) obj);
195                     break;
196                 }
197             case LSPA_IN:
198                 state = State.BANDWIDTH_IN;
199                 if (obj instanceof Bandwidth) {
200                     builder.setBandwidth((Bandwidth) obj);
201                     break;
202                 }
203             case BANDWIDTH_IN:
204                 state = State.METRIC_IN;
205                 if (obj instanceof Metric) {
206                     pathMetrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
207                     state = State.METRIC_IN;
208                     break;
209                 }
210             case METRIC_IN:
211                 state = State.IRO_IN;
212                 if (obj instanceof Iro) {
213                     builder.setIro((Iro) obj);
214                     break;
215                 }
216             case IRO_IN:
217                 state = State.END;
218                 break;
219             case END:
220                 break;
221             default:
222                 break;
223             }
224             if (!state.equals(State.END)) {
225                 objects.remove(0);
226             }
227         }
228         if (!pathMetrics.isEmpty()) {
229             builder.setMetrics(pathMetrics);
230         }
231     }
232
233     protected void parsePath(final PathsBuilder builder, final List<Object> objects) {
234         final List<Metrics> pathMetrics = new ArrayList<>();
235
236         Object obj;
237         State state = State.INIT;
238         while (!objects.isEmpty() && !state.equals(State.END)) {
239             obj = objects.get(0);
240
241             switch (state) {
242             case INIT:
243                 state = State.LSPA_IN;
244                 if (obj instanceof Lspa) {
245                     builder.setLspa((Lspa) obj);
246                     break;
247                 }
248             case LSPA_IN:
249                 state = State.OF_IN;
250                 if (obj instanceof Of) {
251                     builder.setOf((Of) obj);
252                     break;
253                 }
254             case OF_IN:
255                 state = State.BANDWIDTH_IN;
256                 if (obj instanceof Bandwidth) {
257                     builder.setBandwidth((Bandwidth) obj);
258                     break;
259                 }
260             case BANDWIDTH_IN:
261                 state = State.METRIC_IN;
262                 if (obj instanceof Metric) {
263                     pathMetrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
264                     state = State.BANDWIDTH_IN;
265                     break;
266                 }
267             case METRIC_IN:
268                 state = State.IRO_IN;
269                 if (obj instanceof Iro) {
270                     builder.setIro((Iro) obj);
271                     break;
272                 }
273             case IRO_IN:
274                 state = State.END;
275                 break;
276             case END:
277                 break;
278             default:
279                 break;
280             }
281             if (!state.equals(State.END)) {
282                 objects.remove(0);
283             }
284         }
285         if (!pathMetrics.isEmpty()) {
286             builder.setMetrics(pathMetrics);
287         }
288     }
289
290     private enum State {
291         INIT, LSPA_IN, OF_IN, BANDWIDTH_IN, METRIC_IN, IRO_IN, END
292     }
293 }