Pcep Stateful & Initiated renaming
[bgpcep.git] / pcep / ietf-stateful / src / main / java / org / opendaylight / protocol / pcep / ietf / stateful / StatefulPCUpdateRequestMessageParser.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.ietf.stateful;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11
12 import io.netty.buffer.ByteBuf;
13 import io.netty.buffer.Unpooled;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.Optional;
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.ietf.stateful.rev181109.Pcupd;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.PcupdBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.lsp.object.Lsp;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.pcupd.message.PcupdMessageBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.pcupd.message.pcupd.message.Updates;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.pcupd.message.pcupd.message.UpdatesBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.pcupd.message.pcupd.message.updates.Path;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.pcupd.message.pcupd.message.updates.PathBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.srp.object.Srp;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Message;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Object;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.bandwidth.object.Bandwidth;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.Ero;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.include.route.object.Iro;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.Metrics;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.MetricsBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lspa.object.Lspa;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.metric.object.Metric;
40
41 /**
42  * Parser for {@link Pcupd}.
43  */
44 public class StatefulPCUpdateRequestMessageParser extends AbstractMessageParser {
45
46     public static final int TYPE = 11;
47
48     public StatefulPCUpdateRequestMessageParser(final ObjectRegistry registry) {
49         super(registry);
50     }
51
52     @Override
53     public void serializeMessage(final Message message, final ByteBuf out) {
54         checkArgument(message instanceof Pcupd, "Wrong instance of Message. Passed instance of %s. Need Pcupd.",
55             message.getClass());
56         final Pcupd msg = (Pcupd) message;
57         final List<Updates> updates = msg.getPcupdMessage().getUpdates();
58         final ByteBuf buffer = Unpooled.buffer();
59         for (final Updates update : updates) {
60             serializeUpdate(update, buffer);
61         }
62         MessageUtil.formatMessage(TYPE, buffer, out);
63     }
64
65     protected void serializeUpdate(final Updates update, final ByteBuf buffer) {
66         serializeObject(update.getSrp(), buffer);
67         serializeObject(update.getLsp(), buffer);
68         final Path p = update.getPath();
69         if (p != null) {
70             serializeObject(p.getEro(), buffer);
71             serializeObject(p.getLspa(), buffer);
72             serializeObject(p.getBandwidth(), buffer);
73             serializeObject(p.getReoptimizationBandwidth(), buffer);
74             if (p.getMetrics() != null) {
75                 for (final Metrics m : p.getMetrics()) {
76                     serializeObject(m.getMetric(), buffer);
77                 }
78             }
79             serializeObject(p.getIro(), buffer);
80         }
81     }
82
83     @Override
84     protected Message validate(final List<Object> objects, final List<Message> errors)
85             throws PCEPDeserializerException {
86         checkArgument(objects != null, "Passed list can't be null.");
87         if (objects.isEmpty()) {
88             throw new PCEPDeserializerException("Pcup message cannot be empty.");
89         }
90
91         final List<Updates> updateRequests = new ArrayList<>();
92
93         while (!objects.isEmpty()) {
94             final Updates upd = getValidUpdates(objects, errors);
95             if (upd != null) {
96                 updateRequests.add(upd);
97             }
98         }
99         if (!objects.isEmpty()) {
100             throw new PCEPDeserializerException("Unprocessed Objects: " + objects);
101         }
102         return new PcupdBuilder().setPcupdMessage(new PcupdMessageBuilder().setUpdates(updateRequests).build()).build();
103     }
104
105     protected Updates getValidUpdates(final List<Object> objects, final List<Message> errors) {
106         final UpdatesBuilder builder = new UpdatesBuilder();
107
108         Object object = objects.remove(0);
109         if (object instanceof Srp) {
110             builder.setSrp((Srp) object);
111             if (objects.isEmpty()) {
112                 object = null;
113             } else {
114                 object = objects.remove(0);
115             }
116         } else {
117             errors.add(createErrorMsg(PCEPErrors.SRP_MISSING, Optional.empty()));
118         }
119
120         if (validateLsp(object, errors, builder)) {
121             if (!objects.isEmpty()) {
122                 if (!validatePath(objects, errors, builder)) {
123                     return null;
124                 }
125             }
126
127             return builder.build();
128         }
129         return null;
130     }
131
132     private static boolean validateLsp(final Object object, final List<Message> errors, final UpdatesBuilder builder) {
133         if (object instanceof Lsp) {
134             builder.setLsp((Lsp) object);
135         } else {
136             errors.add(createErrorMsg(PCEPErrors.LSP_MISSING, Optional.empty()));
137             return false;
138         }
139         return true;
140     }
141
142     private static boolean validatePath(final List<Object> objects, final List<Message> errors,
143             final UpdatesBuilder builder) {
144         final PathBuilder pBuilder = new PathBuilder();
145         Object object = objects.remove(0);
146         if (object instanceof Ero) {
147             pBuilder.setEro((Ero) object);
148         } else {
149             errors.add(createErrorMsg(PCEPErrors.ERO_MISSING, Optional.empty()));
150             return false;
151         }
152         parsePath(objects, pBuilder);
153         builder.setPath(pBuilder.build());
154         return true;
155     }
156
157     private static void parsePath(final List<Object> objects, final PathBuilder pathBuilder) {
158         final List<Metrics> pathMetrics = new ArrayList<>();
159         Object obj;
160         State state = State.INIT;
161         while (!objects.isEmpty() && !state.equals(State.END)) {
162             obj = objects.get(0);
163             state = insertObject(state,obj, pathBuilder, pathMetrics);
164             if (!state.equals(State.END)) {
165                 objects.remove(0);
166             }
167         }
168         if (!pathMetrics.isEmpty()) {
169             pathBuilder.setMetrics(pathMetrics);
170         }
171     }
172
173     private static State insertObject(final State state, final Object obj, final PathBuilder pathBuilder,
174             final List<Metrics> pathMetrics) {
175         switch (state) {
176             case INIT:
177                 if (obj instanceof Lspa) {
178                     pathBuilder.setLspa((Lspa) obj);
179                     return State.LSPA_IN;
180                 }
181                 // fall through
182             case LSPA_IN:
183                 if (obj instanceof Bandwidth) {
184                     pathBuilder.setBandwidth((Bandwidth) obj);
185                     return State.LSPA_IN;
186                 }
187                 if (obj instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109
188                         .reoptimization.bandwidth.object.ReoptimizationBandwidth) {
189                     pathBuilder.setReoptimizationBandwidth((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns
190                             .yang.pcep.types.rev181109.reoptimization.bandwidth.object.ReoptimizationBandwidth) obj);
191                     return State.LSPA_IN;
192                 }
193                 // fall through
194             case BANDWIDTH_IN:
195                 if (obj instanceof Metric) {
196                     pathMetrics.add(new MetricsBuilder().setMetric((Metric) obj).build());
197                     return State.BANDWIDTH_IN;
198                 }
199                 // fall through
200             case METRIC_IN:
201                 if (obj instanceof Iro) {
202                     pathBuilder.setIro((Iro) obj);
203                     return State.IRO_IN;
204                 }
205                 // fall through
206             case IRO_IN:
207             case END:
208                 return State.END;
209             default:
210                 return state;
211         }
212     }
213
214     private enum State {
215         INIT, LSPA_IN, BANDWIDTH_IN, METRIC_IN, IRO_IN, END
216     }
217 }