dfbf4d0678238af6ec101c9afc6b74e18a300585
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / location / resolver / LocationResolver.java
1 /*
2  * Copyright (c) 2016 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
9 package org.opendaylight.groupbasedpolicy.location.resolver;
10
11 import java.util.Collection;
12 import java.util.Collections;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16
17 import javax.annotation.Nullable;
18
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
21 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
22 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
23 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.groupbasedpolicy.util.IidFactory;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocation;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocationBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocationKey;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocation;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocationBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocationKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.ExternalLocation;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.InternalLocation;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.LocationProviders;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.LocationProvider;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocation;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocationKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderContainmentEndpointLocation;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderContainmentEndpointLocationKey;
41 import org.opendaylight.yangtools.concepts.ListenerRegistration;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 public class LocationResolver implements DataTreeChangeListener<LocationProvider>, AutoCloseable {
47
48     private static final Logger LOG = LoggerFactory.getLogger(LocationResolver.class);
49     private Map<AddressEndpointLocationKey, Map<Long, AbsoluteLocation>> realLocations;
50     private DataBroker dataBroker;
51     private ListenerRegistration<LocationResolver> listenerRegistation;
52
53     public LocationResolver(DataBroker dataBroker) {
54         this.dataBroker = dataBroker;
55         this.realLocations = new HashMap<>();
56         this.listenerRegistation = dataBroker.registerDataTreeChangeListener(
57                 new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
58                         InstanceIdentifier.builder(LocationProviders.class).child(LocationProvider.class).build()),
59                 this);
60     }
61
62     @Override
63     public synchronized void onDataTreeChanged(Collection<DataTreeModification<LocationProvider>> changes) {
64         for (DataTreeModification<LocationProvider> change : changes) {
65             WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
66             switch (change.getRootNode().getModificationType()) {
67                 case DELETE: {
68                     processRemovedLocationProviderData(change.getRootNode().getDataBefore(), wtx);
69                     LOG.debug("Data from location provider {} has been removed",
70                             change.getRootNode().getDataBefore().getProvider().getValue());
71                     break;
72                 }
73                 case WRITE: {
74                     if (change.getRootNode().getDataBefore() != null) {
75                         processRemovedLocationProviderData(change.getRootNode().getDataBefore(), wtx);
76                     }
77                     processCreatedLocationProviderData(change.getRootNode().getDataAfter(), wtx);
78                     LOG.debug("Data from location provider {} has been created",
79                             change.getRootNode().getDataAfter().getProvider().getValue());
80                     break;
81                 }
82                 case SUBTREE_MODIFIED: {
83                     processRemovedLocationProviderData(change.getRootNode().getDataBefore(), wtx);
84                     processCreatedLocationProviderData(change.getRootNode().getDataAfter(), wtx);
85                     LOG.debug("Data from location provider {} has been changed",
86                             change.getRootNode().getDataAfter().getProvider().getValue());
87                     break;
88                 }
89             }
90             wtx.submit();
91         }
92     }
93
94     private void processRemovedLocationProviderData(LocationProvider provider, WriteTransaction wtx) {
95         for (ProviderAddressEndpointLocation addressEndpointLocation : nullToEmpty(
96                 provider.getProviderAddressEndpointLocation())) {
97             AddressEndpointLocationKey epKey = createAddressEndpointLocationKey(addressEndpointLocation.getKey());
98             long priority;
99             if (provider.getPriority() == null) {
100                 priority = 0;
101                 LOG.debug("{} provider doesn't provide priority. Using 0 as priority instead.",
102                         provider.getProvider().getValue());
103             } else {
104                 priority = provider.getPriority();
105             }
106             realLocations.get(epKey).remove(priority);
107             AbsoluteLocation newAbsoluteLocation = getBestAbsoluteLocation(epKey);
108             if (newAbsoluteLocation == null) {
109                 InstanceIdentifier<AbsoluteLocation> iid = IidFactory.absoluteLocationIid(epKey);
110                 wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
111             } else {
112                 AddressEndpointLocationBuilder newEP =
113                         new AddressEndpointLocationBuilder().setKey(epKey).setAbsoluteLocation(newAbsoluteLocation);
114                 InstanceIdentifier<AddressEndpointLocation> iid = IidFactory.addressEndpointLocationIid(newEP.getKey());
115                 wtx.merge(LogicalDatastoreType.OPERATIONAL, iid, newEP.build(), true);
116             }
117             if (addressEndpointLocation.getRelativeLocations() != null) {
118                 for (InternalLocation location : nullToEmpty(
119                         addressEndpointLocation.getRelativeLocations().getInternalLocation())) {
120                     InstanceIdentifier<InternalLocation> iid = IidFactory.internalLocationIid(epKey, location.getKey());
121                     wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
122                 }
123                 for (ExternalLocation location : nullToEmpty(
124                         addressEndpointLocation.getRelativeLocations().getExternalLocation())) {
125                     InstanceIdentifier<ExternalLocation> iid = IidFactory.externalLocationIid(epKey, location.getKey());
126                     wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
127                 }
128             }
129         }
130         for (ProviderContainmentEndpointLocation containmentEndpoint : nullToEmpty(
131                 provider.getProviderContainmentEndpointLocation())) {
132             ContainmentEndpointLocationKey epKey = createContainmentEndpointLocationKey(containmentEndpoint.getKey());
133             if (containmentEndpoint.getRelativeLocations() != null) {
134                 for (InternalLocation location : nullToEmpty(
135                         containmentEndpoint.getRelativeLocations().getInternalLocation())) {
136                     InstanceIdentifier<InternalLocation> iid = IidFactory.internalLocationIid(epKey, location.getKey());
137                     wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
138                 }
139                 for (ExternalLocation location : nullToEmpty(
140                         containmentEndpoint.getRelativeLocations().getExternalLocation())) {
141                     InstanceIdentifier<ExternalLocation> iid = IidFactory.externalLocationIid(epKey, location.getKey());
142                     wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
143                 }
144             }
145         }
146     }
147
148     private void processCreatedLocationProviderData(LocationProvider provider, WriteTransaction wtx) {
149         for (ProviderAddressEndpointLocation addressEndpointLocation : nullToEmpty(
150                 provider.getProviderAddressEndpointLocation())) {
151             AddressEndpointLocationKey epKey = createAddressEndpointLocationKey(addressEndpointLocation.getKey());
152             AddressEndpointLocationBuilder newEP = new AddressEndpointLocationBuilder().setKey(epKey);
153             if (addressEndpointLocation.getAbsoluteLocation() != null) {
154                 if (realLocations.get(epKey) == null) {
155                     realLocations.put(epKey, new HashMap<>());
156                 }
157                 long priority;
158                 if (provider.getPriority() == null) {
159                     priority = 0;
160                     LOG.debug("{} provider doesnt provide priority. Using 0 as priority instead.",
161                             provider.getProvider().getValue());
162                 } else {
163                     priority = provider.getPriority();
164                 }
165                 realLocations.get(epKey).put(priority, addressEndpointLocation.getAbsoluteLocation());
166             }
167             AbsoluteLocation bestLocation = getBestAbsoluteLocation(epKey);
168             if (bestLocation != null) {
169                 newEP.setAbsoluteLocation(bestLocation);
170             }
171             if (addressEndpointLocation.getRelativeLocations() != null) {
172                 newEP.setRelativeLocations(addressEndpointLocation.getRelativeLocations());
173             }
174             InstanceIdentifier<AddressEndpointLocation> iid = IidFactory.addressEndpointLocationIid(newEP.getKey());
175             wtx.merge(LogicalDatastoreType.OPERATIONAL, iid, newEP.build(), true);
176         }
177         for (ProviderContainmentEndpointLocation containmentEndpointLocation : nullToEmpty(
178                 provider.getProviderContainmentEndpointLocation())) {
179             if (containmentEndpointLocation.getRelativeLocations() != null) {
180                 ContainmentEndpointLocationKey key =
181                         createContainmentEndpointLocationKey(containmentEndpointLocation.getKey());
182                 ContainmentEndpointLocationBuilder newEP = new ContainmentEndpointLocationBuilder().setKey(key);
183                 newEP.setRelativeLocations(containmentEndpointLocation.getRelativeLocations());
184                 InstanceIdentifier<ContainmentEndpointLocation> iid =
185                         IidFactory.containmentEndpointLocationIid(newEP.getKey());
186                 wtx.merge(LogicalDatastoreType.OPERATIONAL, iid, newEP.build(), true);
187             }
188         }
189     }
190
191     private AbsoluteLocation getBestAbsoluteLocation(AddressEndpointLocationKey epKey) {
192         if (realLocations.get(epKey) == null) {
193             return null;
194         }
195         long bestPriority = -1;
196         for (long priority : realLocations.get(epKey).keySet()) {
197             bestPriority = bestPriority > priority ? bestPriority : priority;
198         };
199         if (bestPriority == -1) {
200             return null;
201         }
202         return (realLocations.get(epKey).get(new Long(bestPriority)));
203     }
204
205     private AddressEndpointLocationKey createAddressEndpointLocationKey(ProviderAddressEndpointLocationKey key) {
206         return new AddressEndpointLocationKey(key.getAddress(), key.getAddressType(), key.getContextId(),
207                 key.getContextType());
208     }
209
210     private ContainmentEndpointLocationKey createContainmentEndpointLocationKey(
211             ProviderContainmentEndpointLocationKey key) {
212         return new ContainmentEndpointLocationKey(key.getContextId(), key.getContextType());
213     }
214
215     private <T> List<T> nullToEmpty(@Nullable List<T> list) {
216         return list == null ? Collections.emptyList() : list;
217     }
218
219     @Override
220     public void close() throws Exception {
221         listenerRegistation.close();
222     }
223 }