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