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