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