aa9e79ce356f40f7f623b4b35ed09698673c14d9
[transportpce.git] / networkmodel / src / main / java / org / opendaylight / transportpce / networkmodel / service / NetworkModelWavelengthServiceImpl.java
1 /*
2  * Copyright © 2017 AT&T 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.transportpce.networkmodel.service;
9
10 import java.math.BigDecimal;
11 import java.util.Collection;
12 import java.util.HashMap;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Objects;
16 import java.util.Optional;
17 import java.util.concurrent.ExecutionException;
18 import java.util.concurrent.TimeUnit;
19 import java.util.concurrent.TimeoutException;
20 import java.util.stream.Collectors;
21 import org.opendaylight.mdsal.binding.api.DataBroker;
22 import org.opendaylight.mdsal.binding.api.ReadTransaction;
23 import org.opendaylight.mdsal.binding.api.WriteTransaction;
24 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
25 import org.opendaylight.transportpce.common.NetworkUtils;
26 import org.opendaylight.transportpce.common.NodeIdPair;
27 import org.opendaylight.transportpce.common.Timeouts;
28 import org.opendaylight.transportpce.common.fixedflex.FixedFlexImpl;
29 import org.opendaylight.transportpce.common.fixedflex.GridConstant;
30 import org.opendaylight.transportpce.common.fixedflex.GridUtils;
31 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.FrequencyGHz;
32 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.FrequencyTHz;
33 import org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev200529.degree.used.wavelengths.UsedWavelengths;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev200529.degree.used.wavelengths.UsedWavelengthsBuilder;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev200529.degree.used.wavelengths.UsedWavelengthsKey;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.Node1;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.Node1Builder;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.TerminationPoint1;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.TerminationPoint1Builder;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.DegreeAttributes;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.DegreeAttributesBuilder;
42 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.SrgAttributes;
43 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.SrgAttributesBuilder;
44 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.CpAttributes;
45 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.CpAttributesBuilder;
46 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.CtpAttributes;
47 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.CtpAttributesBuilder;
48 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.PpAttributes;
49 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.PpAttributesBuilder;
50 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.RxTtpAttributes;
51 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.RxTtpAttributesBuilder;
52 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.TxTtpAttributes;
53 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.TxTtpAttributesBuilder;
54 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.XpdrClientAttributes;
55 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.XpdrNetworkAttributes;
56 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.XpdrNetworkAttributesBuilder;
57 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.XpdrPortAttributes;
58 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.XpdrPortAttributesBuilder;
59 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.pp.attributes.UsedWavelength;
60 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.pp.attributes.UsedWavelengthBuilder;
61 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.node.termination.point.pp.attributes.UsedWavelengthKey;
62 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.OpenroadmTpType;
63 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.available.freq.map.AvailFreqMaps;
64 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.available.freq.map.AvailFreqMapsKey;
65 import org.opendaylight.yang.gen.v1.http.org.openroadm.xponder.rev200529.xpdr.port.connection.attributes.Wavelength;
66 import org.opendaylight.yang.gen.v1.http.org.openroadm.xponder.rev200529.xpdr.port.connection.attributes.WavelengthBuilder;
67 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201126.path.description.AToZDirection;
68 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201126.path.description.ZToADirection;
69 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201126.path.description.atoz.direction.AToZ;
70 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201126.path.description.ztoa.direction.ZToA;
71 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev201126.pce.resource.resource.resource.TerminationPoint;
72 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NetworkId;
73 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.Networks;
74 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
75 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.Network;
76 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.NetworkKey;
77 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.NodeKey;
78 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.TpId;
79 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPointKey;
80 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
81 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
82 import org.slf4j.Logger;
83 import org.slf4j.LoggerFactory;
84
85 public class NetworkModelWavelengthServiceImpl implements NetworkModelWavelengthService {
86
87     private static final Logger LOG = LoggerFactory.getLogger(NetworkModelWavelengthServiceImpl.class);
88     private final DataBroker dataBroker;
89     private final AvailFreqMapsKey availFreqMapKey = new AvailFreqMapsKey(GridConstant.C_BAND);
90
91     public NetworkModelWavelengthServiceImpl(DataBroker dataBroker) {
92         this.dataBroker = dataBroker;
93     }
94
95     @Override
96     public void useWavelengths(AToZDirection atoZDirection, ZToADirection ztoADirection) {
97         if (atoZDirection != null && atoZDirection.getAToZWavelengthNumber() != null) {
98             LOG.info("Update wavelength for a to z direction {}", atoZDirection);
99             List<NodeIdPair> atozTpIds = getAToZTpList(atoZDirection);
100             atozTpIds.removeIf(Objects::isNull);
101             deleteAvailableWL(atozTpIds.stream().map(NodeIdPair::getNodeID).distinct().collect(Collectors.toList()),
102                     atoZDirection.getAToZWavelengthNumber().toJava());
103             addUsedWL(atoZDirection.getAToZWavelengthNumber().toJava(), atozTpIds);
104         }
105         if (ztoADirection != null && ztoADirection.getZToAWavelengthNumber() != null) {
106             LOG.info("Update wavelength for z to a direction {}", ztoADirection);
107             List<NodeIdPair> ztoaTpIds = getZToATpList(ztoADirection);
108             ztoaTpIds.removeIf(Objects::isNull);
109             deleteAvailableWL(ztoaTpIds.stream().map(NodeIdPair::getNodeID).distinct().collect(Collectors.toList()),
110                     ztoADirection.getZToAWavelengthNumber().toJava());
111
112             addUsedWL(ztoADirection.getZToAWavelengthNumber().toJava(), ztoaTpIds);
113         }
114     }
115
116
117     @Override
118     public void freeWavelengths(AToZDirection atoZDirection, ZToADirection ztoADirection) {
119         if (atoZDirection != null && atoZDirection.getAToZWavelengthNumber() != null) {
120             LOG.info("Free wavelength for a to z direction {}", atoZDirection);
121             List<NodeIdPair> atozTpIds = getAToZTpList(atoZDirection);
122             atozTpIds.removeIf(Objects::isNull);
123             deleteUsedWL(atoZDirection.getAToZWavelengthNumber().toJava(), atozTpIds);
124             addAvailableWL(atozTpIds.stream().map(NodeIdPair::getNodeID).distinct().collect(Collectors.toList()),
125                     atoZDirection.getAToZWavelengthNumber().toJava());
126         }
127         if (ztoADirection != null && ztoADirection.getZToAWavelengthNumber() != null) {
128             LOG.info("Free wavelength for z to a direction {}", ztoADirection);
129             List<NodeIdPair> ztoaTpIds = getZToATpList(ztoADirection);
130             ztoaTpIds.removeIf(Objects::isNull);
131             deleteUsedWL(ztoADirection.getZToAWavelengthNumber().toJava(), ztoaTpIds);
132             addAvailableWL(ztoaTpIds.stream().map(NodeIdPair::getNodeID).distinct().collect(Collectors.toList()),
133                     ztoADirection.getZToAWavelengthNumber().toJava());
134         }
135     }
136
137     private List<NodeIdPair> getAToZTpList(AToZDirection atoZDirection) {
138         Collection<AToZ> atozList = atoZDirection.nonnullAToZ().values();
139         return atozList.stream()
140                 .filter(aToZ -> {
141                     if ((aToZ.getResource() == null) || (aToZ.getResource().getResource() == null)) {
142                         LOG.warn("Resource of AToZ node {} is null! Skipping this node!", aToZ.getId());
143                         return false;
144                     }
145                     return aToZ.getResource().getResource() instanceof TerminationPoint;
146                 }).map(aToZ -> {
147                     TerminationPoint tp = (TerminationPoint) aToZ.getResource().getResource();
148                     if ((tp == null) || (tp.getTpNodeId() == null) ||  (tp.getTpId() == null)
149                         || tp.getTpId().isEmpty()) {
150                         LOG.warn("Termination point in AToZ node {} contains nulls! Skipping this node!", aToZ.getId());
151                         return null;
152                     }
153                     return new NodeIdPair(tp.getTpNodeId(), tp.getTpId());
154                 }).collect(Collectors.toList());
155     }
156
157     private List<NodeIdPair> getZToATpList(ZToADirection ztoADirection) {
158         Collection<ZToA> ztoaList = ztoADirection.nonnullZToA().values();
159         return ztoaList.stream()
160                 .filter(zToA -> {
161                     if ((zToA.getResource() == null) || (zToA.getResource().getResource() == null)) {
162                         LOG.warn("Resource of ZToA node {} is null! Skipping this node!", zToA.getId());
163                         return false;
164                     }
165                     return zToA.getResource().getResource() instanceof TerminationPoint;
166                 }).map(zToA -> {
167                     TerminationPoint tp = (TerminationPoint) zToA.getResource().getResource();
168                     if ((tp == null) || (tp.getTpNodeId() == null) ||  (tp.getTpId() == null)
169                         || tp.getTpId().isEmpty()) {
170                         LOG.warn("Termination point in ZToA node {} contains nulls! Skipping this node!", zToA.getId());
171                         return null;
172                     }
173                     return new NodeIdPair(tp.getTpNodeId(), tp.getTpId());
174                 }).collect(Collectors.toList());
175     }
176
177     private InstanceIdentifier<Node1> createNode1IID(String nodeId) {
178         return InstanceIdentifier
179                 .builder(Networks.class)
180                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
181                 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226
182                         .networks.network.Node.class, new NodeKey(new NodeId(nodeId)))
183                 .augmentation(Node1.class).build();
184     }
185
186     private InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529
187             .Node1> createNode2IID(String nodeId) {
188         return InstanceIdentifier
189                 .builder(Networks.class)
190                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
191                 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226
192                         .networks.network.Node.class, new NodeKey(new NodeId(nodeId)))
193                 .augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Node1.class)
194                 .build();
195     }
196
197     private Optional<Node1> getNode1FromDatastore(String nodeId) {
198         InstanceIdentifier<Node1>
199                 nodeIID = createNode1IID(nodeId);
200         Optional<Node1> nodeOpt;
201         try (ReadTransaction nodeReadTx = this.dataBroker.newReadOnlyTransaction()) {
202             nodeOpt = nodeReadTx.read(LogicalDatastoreType.CONFIGURATION, nodeIID)
203                     .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
204         } catch (InterruptedException | ExecutionException | TimeoutException e) {
205             LOG.warn("Exception while getting node from {} topology!", NetworkUtils.OVERLAY_NETWORK_ID, e);
206             nodeOpt = Optional.empty();
207         }
208         return nodeOpt;
209     }
210
211     private Optional<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529
212             .Node1> getNode2FromDatastore(String nodeId) {
213         InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Node1>
214                 nodeIID = createNode2IID(nodeId);
215         Optional<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Node1> nodeOpt;
216         try (ReadTransaction nodeReadTx = this.dataBroker.newReadOnlyTransaction()) {
217             nodeOpt = nodeReadTx.read(LogicalDatastoreType.CONFIGURATION, nodeIID)
218                     .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
219         } catch (InterruptedException | ExecutionException | TimeoutException e) {
220             LOG.warn("Exception while getting node from {} topology!", NetworkUtils.OVERLAY_NETWORK_ID, e);
221             nodeOpt = Optional.empty();
222         }
223         return nodeOpt;
224     }
225
226     private void addAvailableWL(List<String> nodeIds, Long wavelengthNumber) {
227         updateFreqMaps4Nodes(nodeIds, wavelengthNumber, true);
228     }
229
230     private void deleteAvailableWL(List<String> nodeIds, Long wavelengthNumber) {
231         updateFreqMaps4Nodes(nodeIds, wavelengthNumber, false);
232     }
233
234     private InstanceIdentifierBuilder<TerminationPoint1> createTerminationPoint1IIDBuilder(String nodeId, String tpId) {
235         return InstanceIdentifier
236                 .builder(Networks.class)
237                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
238                 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226
239                         .networks.network.Node.class, new NodeKey(new NodeId(nodeId)))
240                 .augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
241                         .Node1.class)
242                 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
243                         .networks.network.node.TerminationPoint.class, new TerminationPointKey(new TpId(tpId)))
244                 .augmentation(TerminationPoint1.class);
245     }
246
247     private InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529
248             .TerminationPoint1> createTerminationPoint2IIDBuilder(String nodeId, String tpId) {
249         return InstanceIdentifier
250                 .builder(Networks.class)
251                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
252                 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226
253                         .networks.network.Node.class, new NodeKey(new NodeId(nodeId)))
254                 .augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
255                         .Node1.class)
256                 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
257                         .networks.network.node.TerminationPoint.class, new TerminationPointKey(new TpId(tpId)))
258                 .augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529
259                     .TerminationPoint1.class);
260     }
261
262     private Optional<TerminationPoint1> getTerminationPoint1FromDatastore(String nodeId, String tpId) {
263         InstanceIdentifier<TerminationPoint1> tpIID = createTerminationPoint1IIDBuilder(nodeId, tpId).build();
264         Optional<TerminationPoint1> tpOpt;
265         try (ReadTransaction readTx = this.dataBroker.newReadOnlyTransaction()) {
266             tpOpt = readTx.read(LogicalDatastoreType.CONFIGURATION, tpIID)
267                     .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
268         } catch (InterruptedException | ExecutionException | TimeoutException e) {
269             LOG.warn("Exception while getting termination point from {} topology!",
270                     NetworkUtils.OVERLAY_NETWORK_ID, e);
271             tpOpt = Optional.empty();
272         }
273         return tpOpt;
274     }
275
276     private Optional<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529
277             .TerminationPoint1> getTerminationPoint2FromDatastore(String nodeId, String tpId) {
278         InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.TerminationPoint1>
279             tpIID = createTerminationPoint2IIDBuilder(nodeId, tpId).build();
280         Optional<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.TerminationPoint1> tpOpt;
281         try (ReadTransaction readTx = this.dataBroker.newReadOnlyTransaction()) {
282             tpOpt = readTx.read(LogicalDatastoreType.CONFIGURATION, tpIID)
283                     .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
284         } catch (InterruptedException | ExecutionException | TimeoutException e) {
285             LOG.warn("Exception while getting termination point from {} topology!",
286                     NetworkUtils.OVERLAY_NETWORK_ID, e);
287             tpOpt = Optional.empty();
288         }
289         return tpOpt;
290     }
291
292     private void deleteUsedWL(long wavelengthIndex, List<NodeIdPair> tpIds) {
293         WriteTransaction deleteUsedWlTx = this.dataBroker.newWriteOnlyTransaction();
294         for (NodeIdPair idPair : tpIds) {
295             Optional<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.TerminationPoint1>
296                 tp2Opt = getTerminationPoint2FromDatastore(idPair.getNodeID(), idPair.getTpID());
297
298             OpenroadmTpType tpType;
299             if (!tp2Opt.isPresent()) {
300                 LOG.error("Unable to get termination point {} from topology {}! Skipping removal of used wavelength"
301                         + " for this node.", idPair.getTpID(), NetworkUtils.OVERLAY_NETWORK_ID);
302                 continue;
303             }
304             tpType = tp2Opt.get().getTpType();
305             Optional<TerminationPoint1> tp1Opt =
306                 getTerminationPoint1FromDatastore(idPair.getNodeID(), idPair.getTpID());
307             InstanceIdentifier.InstanceIdentifierBuilder<TerminationPoint1> usedWlIIDBuilder =
308                     createTerminationPoint1IIDBuilder(idPair.getNodeID(), idPair.getTpID());
309             switch (tpType) {
310                 case DEGREETXTTP:
311                 case DEGREETXRXTTP:
312                     deleteUsedWlTx.delete(LogicalDatastoreType.CONFIGURATION,
313                             usedWlIIDBuilder.child(TxTtpAttributes.class).child(UsedWavelengths.class,
314                                     new UsedWavelengthsKey((int)wavelengthIndex)).build());
315                     break;
316
317                 case DEGREERXTTP:
318                     deleteUsedWlTx.delete(LogicalDatastoreType.CONFIGURATION,
319                             usedWlIIDBuilder.child(RxTtpAttributes.class).child(UsedWavelengths.class,
320                                     new UsedWavelengthsKey((int)wavelengthIndex)).build());
321                     break;
322
323                 case DEGREETXCTP:
324                 case DEGREERXCTP:
325                 case DEGREETXRXCTP:
326                     if (tp1Opt.isPresent()) {
327                         TerminationPoint1 tp1 = tp1Opt.get();
328                         TerminationPoint1Builder tp1Builder = new TerminationPoint1Builder(tp1);
329                         CtpAttributesBuilder ctpAttributesBuilder;
330                         if (tp1Builder.getCtpAttributes() != null) {
331                             ctpAttributesBuilder = new CtpAttributesBuilder(tp1Builder.getCtpAttributes());
332                             Map<AvailFreqMapsKey, AvailFreqMaps> availFreqMapsMap = tp1Builder.getCtpAttributes()
333                                     .nonnullAvailFreqMaps();
334                             ctpAttributesBuilder
335                                     .setAvailFreqMaps(updateFreqMaps(wavelengthIndex, availFreqMapsMap, true));
336                             deleteUsedWlTx.merge(LogicalDatastoreType.CONFIGURATION,
337                                     createTerminationPoint1IIDBuilder(idPair.getNodeID(),
338                                             idPair.getTpID()).build(), tp1Builder.build());
339                         }
340                     }
341                     break;
342
343                 case SRGTXCP:
344                 case SRGRXCP:
345                 case SRGTXRXCP:
346                     if (tp1Opt.isPresent()) {
347                         TerminationPoint1 tp1 = tp1Opt.get();
348                         TerminationPoint1Builder tp1Builder = new TerminationPoint1Builder(tp1);
349                         CpAttributesBuilder cpAttributesBuilder;
350                         if (tp1Builder.getCpAttributes() != null) {
351                             cpAttributesBuilder = new CpAttributesBuilder(tp1Builder.getCpAttributes());
352                             Map<AvailFreqMapsKey, AvailFreqMaps> availFreqMapsMap = tp1Builder.getCpAttributes()
353                                     .nonnullAvailFreqMaps();
354                             cpAttributesBuilder
355                                     .setAvailFreqMaps(updateFreqMaps(wavelengthIndex, availFreqMapsMap, true));
356                             deleteUsedWlTx.merge(LogicalDatastoreType.CONFIGURATION,
357                                     createTerminationPoint1IIDBuilder(idPair.getNodeID(),
358                                             idPair.getTpID()).build(), tp1Builder.build());
359                         }
360                     }
361                     break;
362
363                 case SRGTXRXPP:
364                 case SRGRXPP:
365                 case SRGTXPP:
366                     deleteUsedWlTx.delete(LogicalDatastoreType.CONFIGURATION,
367                             usedWlIIDBuilder.child(PpAttributes.class).child(UsedWavelength.class,
368                                     new UsedWavelengthKey((int)wavelengthIndex)).build());
369                     break;
370
371                 case XPONDERNETWORK:
372                     deleteUsedWlTx.delete(LogicalDatastoreType.CONFIGURATION,
373                             usedWlIIDBuilder.child(XpdrNetworkAttributes.class).child(Wavelength.class).build());
374                     break;
375                 case XPONDERCLIENT:
376                     deleteUsedWlTx.delete(LogicalDatastoreType.CONFIGURATION,
377                             usedWlIIDBuilder.child(XpdrClientAttributes.class).child(Wavelength.class).build());
378                     break;
379                 case XPONDERPORT:
380                     deleteUsedWlTx.delete(LogicalDatastoreType.CONFIGURATION,
381                             usedWlIIDBuilder.child(XpdrPortAttributes.class).child(Wavelength.class).build());
382                     break;
383
384                 default:
385                     break;
386             }
387         }
388         try {
389             deleteUsedWlTx.commit().get(Timeouts.DATASTORE_DELETE, TimeUnit.MILLISECONDS);
390         } catch (InterruptedException | ExecutionException | TimeoutException e) {
391             List<String> tpIdsString = tpIds.stream().map(NodeIdPair::toString).collect(Collectors.toList());
392             LOG.error("Unable to delete used WL {} from TPs {}!", wavelengthIndex, String.join(", ", tpIdsString), e);
393         }
394     }
395
396     private void addUsedWL(long wavelengthIndex, List<NodeIdPair> tpIds) {
397         WriteTransaction addUsedWlTx = this.dataBroker.newWriteOnlyTransaction();
398         FixedFlexImpl fixedFlex = new FixedFlexImpl(wavelengthIndex);
399         FrequencyTHz centralTHz = new FrequencyTHz(new BigDecimal(fixedFlex.getCenterFrequency()));
400         Map<AvailFreqMapsKey, AvailFreqMaps> availFreqMapsMap;
401         for (NodeIdPair idPair : tpIds) {
402             Optional<TerminationPoint1> tp1Opt =
403                 getTerminationPoint1FromDatastore(idPair.getNodeID(), idPair.getTpID());
404             TerminationPoint1 tp1 = null;
405             Optional<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529
406                 .TerminationPoint1> tp2Opt = getTerminationPoint2FromDatastore(idPair.getNodeID(), idPair.getTpID());
407             org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.TerminationPoint1 tp2;
408             if (!tp2Opt.isPresent()) {
409                 LOG.error(
410                     "Unable to get common-network termination point {} from topology {}! Skip removal of used"
411                     + "wavelength for the node", idPair.getTpID(), NetworkUtils.OVERLAY_NETWORK_ID);
412                 continue;
413             }
414             tp2 = tp2Opt.get();
415             TerminationPoint1Builder tp1Builder;
416             if (tp1Opt.isPresent()) {
417                 tp1 = tp1Opt.get();
418                 tp1Builder = new TerminationPoint1Builder(tp1);
419             } else {
420                 tp1Builder = new TerminationPoint1Builder();
421             }
422
423             UsedWavelengths usedWaveLength = new UsedWavelengthsBuilder()
424                     .setIndex((int)wavelengthIndex)
425                     .setFrequency(centralTHz)
426                     .setWidth(FrequencyGHz.getDefaultInstance("40"))
427                     .build();
428             switch (tp2.getTpType()) {
429                 case DEGREETXTTP:
430                 case DEGREETXRXTTP:
431                     TxTtpAttributes txTtpAttributes = null;
432                     Map<UsedWavelengthsKey,UsedWavelengths> usedDegreeTxTtpWls;
433                     if (tp1 != null) {
434                         txTtpAttributes = tp1.getTxTtpAttributes();
435                     }
436                     TxTtpAttributesBuilder txTtpAttributesBuilder;
437                     usedDegreeTxTtpWls = new HashMap<>();
438                     if (txTtpAttributes == null) {
439                         txTtpAttributesBuilder = new TxTtpAttributesBuilder();
440                     } else {
441                         txTtpAttributesBuilder = new TxTtpAttributesBuilder(txTtpAttributes);
442                         usedDegreeTxTtpWls.putAll(txTtpAttributesBuilder.getUsedWavelengths());
443                     }
444                     usedDegreeTxTtpWls.put(usedWaveLength.key(),usedWaveLength);
445                     txTtpAttributesBuilder.setUsedWavelengths(usedDegreeTxTtpWls);
446                     tp1Builder.setTxTtpAttributes(txTtpAttributesBuilder.build());
447                     break;
448
449                 case DEGREERXTTP:
450                     RxTtpAttributes rxTtpAttributes = null;
451                     Map<UsedWavelengthsKey,UsedWavelengths> usedDegreeRxTtpWls;
452                     if (tp1 != null) {
453                         rxTtpAttributes = tp1.getRxTtpAttributes();
454                     }
455                     RxTtpAttributesBuilder rxTtpAttributesBuilder;
456                     usedDegreeRxTtpWls = new HashMap<>();
457                     if (rxTtpAttributes == null) {
458                         rxTtpAttributesBuilder = new RxTtpAttributesBuilder();
459                     } else {
460                         rxTtpAttributesBuilder = new RxTtpAttributesBuilder(rxTtpAttributes);
461                         usedDegreeRxTtpWls.putAll(rxTtpAttributesBuilder.getUsedWavelengths());
462                     }
463                     usedDegreeRxTtpWls.put(usedWaveLength.key(),usedWaveLength);
464                     rxTtpAttributesBuilder.setUsedWavelengths(usedDegreeRxTtpWls);
465                     tp1Builder.setRxTtpAttributes(rxTtpAttributesBuilder.build());
466                     break;
467
468                 case DEGREETXCTP:
469                 case DEGREERXCTP:
470                 case DEGREETXRXCTP:
471                     CtpAttributes ctpAttributes = null;
472                     if (tp1 != null) {
473                         ctpAttributes = tp1.getCtpAttributes();
474                     }
475                     CtpAttributesBuilder ctpAttributesBuilder;
476                     if (ctpAttributes == null) {
477                         ctpAttributesBuilder = new CtpAttributesBuilder();
478                     } else {
479                         ctpAttributesBuilder = new CtpAttributesBuilder(ctpAttributes);
480                     }
481                     availFreqMapsMap = ctpAttributesBuilder.getAvailFreqMaps();
482                     ctpAttributesBuilder.setAvailFreqMaps(updateFreqMaps(wavelengthIndex, availFreqMapsMap, false));
483                     tp1Builder.setCtpAttributes(ctpAttributesBuilder.build());
484                     break;
485
486                 case SRGTXCP:
487                 case SRGRXCP:
488                 case SRGTXRXCP:
489                     CpAttributes cpAttributes = null;
490                     if (tp1 != null) {
491                         cpAttributes = tp1.getCpAttributes();
492                     }
493                     CpAttributesBuilder cpAttributesBuilder;
494                     if (cpAttributes == null) {
495                         cpAttributesBuilder = new CpAttributesBuilder();
496                     } else {
497                         cpAttributesBuilder = new CpAttributesBuilder(cpAttributes);
498                     }
499                     availFreqMapsMap = cpAttributesBuilder.getAvailFreqMaps();
500                     cpAttributesBuilder.setAvailFreqMaps(updateFreqMaps(wavelengthIndex, availFreqMapsMap, false));
501                     tp1Builder.setCpAttributes(cpAttributesBuilder.build());
502                     break;
503
504                 case SRGTXRXPP:
505                 case SRGRXPP:
506                 case SRGTXPP:
507                     PpAttributes ppAttributes = null;
508                     Map<UsedWavelengthKey, UsedWavelength> usedDegreePpWls;
509                     if (tp1 != null) {
510                         ppAttributes = tp1.getPpAttributes();
511                     }
512                     PpAttributesBuilder ppAttributesBuilder;
513                     usedDegreePpWls = new HashMap<>();
514                     if (ppAttributes == null) {
515                         ppAttributesBuilder = new PpAttributesBuilder();
516                     } else {
517                         ppAttributesBuilder = new PpAttributesBuilder(ppAttributes);
518                         usedDegreePpWls.putAll(ppAttributesBuilder.getUsedWavelength());
519                     }
520                     UsedWavelength usedDegreeWaveLength = new UsedWavelengthBuilder()
521                             .setIndex((int)wavelengthIndex)
522                             .setFrequency(centralTHz).setWidth(FrequencyGHz.getDefaultInstance("40")).build();
523                     usedDegreePpWls.put(usedDegreeWaveLength.key(),usedDegreeWaveLength);
524                     ppAttributesBuilder.setUsedWavelength(usedDegreePpWls);
525                     tp1Builder.setPpAttributes(ppAttributesBuilder.build());
526                     break;
527
528                 case XPONDERNETWORK:
529                     XpdrNetworkAttributes xpdrNetworkAttributes = null;
530                     if (tp1 != null) {
531                         xpdrNetworkAttributes = tp1.getXpdrNetworkAttributes();
532                     }
533                     XpdrNetworkAttributesBuilder xpdrNetworkAttributesBuilder;
534                     if (xpdrNetworkAttributes == null) {
535                         xpdrNetworkAttributesBuilder = new XpdrNetworkAttributesBuilder();
536                     } else {
537                         xpdrNetworkAttributesBuilder = new XpdrNetworkAttributesBuilder(xpdrNetworkAttributes);
538                     }
539                     Wavelength usedXpdrNetworkWl = new WavelengthBuilder()
540                         .setWidth(FrequencyGHz.getDefaultInstance("40")).setFrequency(centralTHz).build();
541                     tp1Builder.setXpdrNetworkAttributes(xpdrNetworkAttributesBuilder.setWavelength(usedXpdrNetworkWl)
542                         .build());
543                     break;
544                 case XPONDERCLIENT:
545                     break;
546                 case XPONDERPORT:
547                     XpdrPortAttributes xpdrPortAttributes = null;
548                     if (tp1 != null) {
549                         xpdrPortAttributes = tp1.getXpdrPortAttributes();
550                     }
551                     XpdrPortAttributesBuilder xpdrPortAttributesBuilder;
552                     if (xpdrPortAttributes == null) {
553                         xpdrPortAttributesBuilder = new XpdrPortAttributesBuilder();
554                     } else {
555                         xpdrPortAttributesBuilder = new XpdrPortAttributesBuilder(xpdrPortAttributes);
556                     }
557                     Wavelength usedXpdrPortWl = new WavelengthBuilder().setWidth(FrequencyGHz.getDefaultInstance("40"))
558                         .setFrequency(centralTHz).build();
559                     tp1Builder.setXpdrPortAttributes(xpdrPortAttributesBuilder.setWavelength(usedXpdrPortWl)
560                         .build());
561                     break;
562
563                 default:
564                     // TODO skip for now
565                     continue;
566             }
567             addUsedWlTx.put(LogicalDatastoreType.CONFIGURATION, createTerminationPoint1IIDBuilder(idPair.getNodeID(),
568                     idPair.getTpID()).build(), tp1Builder.build());
569         }
570         try {
571             addUsedWlTx.commit().get(Timeouts.DATASTORE_WRITE, TimeUnit.MILLISECONDS);
572         } catch (InterruptedException | ExecutionException | TimeoutException e) {
573             List<String> tpIdsString = tpIds.stream().map(NodeIdPair::toString).collect(Collectors.toList());
574             LOG.error("Unable to add used WL {} for TPs {}!", wavelengthIndex, String.join(", ", tpIdsString), e);
575         }
576     }
577
578     /**
579      * Update availFreqMapsMap for wavelengthNumber for nodes in nodeIds.
580      * @param nodeIds List of node id.
581      * @param wavelengthNumber Long
582      * @param isSlotAvailable boolean true if waveLength is available, false otherwise.
583      */
584     //TODO: reduce its Cognitive Complexity from 21 to the 15
585     private void updateFreqMaps4Nodes(List<String> nodeIds, Long wavelengthNumber, boolean isSlotAvailable) {
586         WriteTransaction nodeWriteTx = this.dataBroker.newWriteOnlyTransaction();
587         Map<AvailFreqMapsKey, AvailFreqMaps> availFreqMapsMap;
588         String action = isSlotAvailable ? "addition" : "deletion";
589         for (String nodeId : nodeIds) {
590             Optional<Node1> node1Opt = getNode1FromDatastore(nodeId);
591             Optional<org.opendaylight.yang.gen.v1
592                 .http.org.openroadm.common.network.rev200529.Node1> node2Opt = getNode2FromDatastore(nodeId);
593             if (!node1Opt.isPresent() || !node2Opt.isPresent()) {
594                 LOG.error(
595                         "From topology {} for node id {} -> Get common-network : {} ! "
596                                 + "Get network-topology : {} ! Skipping {} of available wavelength for this node.",
597                         NetworkUtils.OVERLAY_NETWORK_ID, nodeId, node1Opt.isPresent(), node2Opt.isPresent(), action);
598                 continue;
599             }
600             Node1 node1 = node1Opt.get();
601             org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Node1 node2 = node2Opt.get();
602             Node1Builder node1Builder = new Node1Builder(node1);
603             switch (node2.getNodeType()) {
604                 case DEGREE:
605                     DegreeAttributes degreeAttributes = node1.getDegreeAttributes();
606                     DegreeAttributesBuilder degreeAttributesBuilder = degreeAttributes == null
607                         ? new DegreeAttributesBuilder() : new DegreeAttributesBuilder(degreeAttributes);
608                     availFreqMapsMap = degreeAttributesBuilder.getAvailFreqMaps();
609                     degreeAttributesBuilder
610                         .setAvailFreqMaps(updateFreqMaps(wavelengthNumber, availFreqMapsMap, isSlotAvailable));
611                     node1Builder.setDegreeAttributes(degreeAttributesBuilder.build());
612                     break;
613                 case SRG:
614                     SrgAttributes srgAttributes = node1.getSrgAttributes();
615                     SrgAttributesBuilder srgAttributesBuilder = srgAttributes == null
616                         ? new SrgAttributesBuilder() : new SrgAttributesBuilder(srgAttributes);
617                     availFreqMapsMap = srgAttributesBuilder.getAvailFreqMaps();
618                     srgAttributesBuilder
619                         .setAvailFreqMaps(updateFreqMaps(wavelengthNumber, availFreqMapsMap, isSlotAvailable));
620                     node1Builder.setSrgAttributes(srgAttributesBuilder.build());
621                     break;
622                 default:
623                     LOG.warn("Node type not managed {}", node2.getNodeType());
624                     break;
625             }
626             nodeWriteTx.put(LogicalDatastoreType.CONFIGURATION, createNode1IID(nodeId), node1Builder.build());
627         }
628         try {
629             nodeWriteTx.commit().get(Timeouts.DATASTORE_WRITE, TimeUnit.MILLISECONDS);
630         } catch (ExecutionException | TimeoutException e) {
631             LOG.error("Cannot perform {} WL {} for nodes {}!", action, wavelengthNumber, String.join(", ", nodeIds), e);
632         } catch (InterruptedException e) {
633             LOG.error("{} interrupted  WL {} for nodes {}!", action, wavelengthNumber, String.join(", ", nodeIds), e);
634             Thread.currentThread().interrupt();
635         }
636     }
637
638     /**
639      * Update availFreqMapsMap for wavelengthNumber.
640      * @param wavelengthNumber Long
641      * @param availFreqMapsMap Map
642      * @param isSlotAvailable boolean
643      * @return availFreqMapsMap updated for wavelengthNumber.
644      */
645     private Map<AvailFreqMapsKey, AvailFreqMaps> updateFreqMaps(Long wavelengthNumber,
646             Map<AvailFreqMapsKey, AvailFreqMaps> availFreqMapsMap, boolean isSlotAvailable) {
647         byte slotValue = isSlotAvailable ? (byte)GridConstant.AVAILABLE_SLOT_VALUE : (byte)GridConstant.USED_SLOT_VALUE;
648         if (availFreqMapsMap == null) {
649             availFreqMapsMap = GridUtils.initFreqMaps4FixedGrid2Available();
650         }
651         AvailFreqMaps availFreqMaps = availFreqMapsMap.get(availFreqMapKey);
652         if (availFreqMaps != null && availFreqMaps.getFreqMap() != null) {
653             int intWlNumber = wavelengthNumber.intValue();
654             if (intWlNumber > 0 && intWlNumber <= availFreqMaps.getFreqMap().length) {
655                 availFreqMaps.getFreqMap()[intWlNumber - 1] = slotValue;
656             }
657         }
658         return availFreqMapsMap;
659     }
660 }