Add INFO.yaml for GBP
[groupbasedpolicy.git] / neutron-vpp-mapper / src / main / java / org / opendaylight / groupbasedpolicy / neutron / vpp / mapper / processors / NeutronListener.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.neutron.vpp.mapper.processors;
10
11 import java.io.Closeable;
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.LinkedHashSet;
15 import java.util.List;
16 import java.util.Set;
17 import java.util.concurrent.ExecutionException;
18
19 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
22 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
23 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
24 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
27 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
28 import org.opendaylight.yangtools.concepts.ListenerRegistration;
29 import org.opendaylight.yangtools.yang.binding.DataObject;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
31 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 import com.google.common.annotations.VisibleForTesting;
36 import com.google.common.collect.Iterators;
37 import com.google.common.collect.PeekingIterator;
38
39 public class NeutronListener implements ClusteredDataTreeChangeListener<Neutron>, Closeable {
40
41     private static final Logger LOG = LoggerFactory.getLogger(NeutronListener.class);
42
43     private final Set<MappingProvider<? extends DataObject>> dataChangeProviders = new LinkedHashSet<>();
44     protected ListenerRegistration<NeutronListener> registeredListener;
45
46     public NeutronListener(DataBroker dataBroker, NodeId routingNode) {
47         LOG.info("Routing node chosen in ODL is {}", routingNode);
48         registerHandlersAndListeners(dataBroker, routingNode);
49         registeredListener = dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(
50                 LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.builder(Neutron.class).build()), this);
51     }
52
53     private void registerHandlersAndListeners(DataBroker dataBroker, NodeId routingNode) {
54         PortHandler portHandler = new PortHandler(dataBroker, routingNode);
55         dataChangeProviders.add(new PortAware(portHandler, dataBroker));
56         dataChangeProviders.add(new NetworkAware(dataBroker));
57         dataChangeProviders.add(new SubnetAware(dataBroker));
58     }
59
60     @Override
61     public void onDataTreeChanged(Collection<DataTreeModification<Neutron>> changes) {
62         for (DataTreeModification<Neutron> change : changes) {
63             DataObjectModification<Neutron> rootNode = change.getRootNode();
64             for (MappingProvider<? extends DataObject> provider : dataChangeProviders) {
65                 for (DataObjectModification<? extends DataObject> modDto : findModifiedData(provider, rootNode)) {
66                     try {
67                         processChangedData(modDto, modDto.getModificationType(), provider);
68                     } catch (InterruptedException | ExecutionException e) {
69                         LOG.error("Failed to process {} modification of node: {}. {}", modDto.getModificationType(),
70                                 modDto.getIdentifier(), e.getStackTrace());
71                     }
72                 }
73             }
74         }
75     }
76
77     List<DataObjectModification<? extends DataObject>> findModifiedData(MappingProvider<? extends DataObject> provider,
78             DataObjectModification<Neutron> rootNode) {
79         List<DataObjectModification<? extends DataObject>> modDtos = new ArrayList<>();
80         PeekingIterator<PathArgument> pathArgs = Iterators.peekingIterator(provider.getNeutronDtoIid()
81             .getPathArguments()
82             .iterator());
83         DataObjectModification<? extends DataObject> modifDto = rootNode;
84         while (pathArgs.hasNext()) {
85             pathArgs.next();
86             for (DataObjectModification<? extends DataObject> childDto : modifDto.getModifiedChildren()) {
87                 if (pathArgs.hasNext() && childDto.getDataType().equals(pathArgs.peek().getType())) {
88                     if (childDto.getDataType().equals(provider.getNeutronDtoIid().getTargetType())) {
89                         modDtos.add(childDto);
90                     } else {
91                         modifDto = childDto;
92                         break;
93                     }
94                 }
95             }
96         }
97         return modDtos;
98     }
99
100     @SuppressWarnings("unchecked")
101     <T extends DataObject> void processChangedData(DataObjectModification<?> dto, ModificationType m,
102             MappingProvider<T> processor) throws InterruptedException, ExecutionException {
103         switch (m) {
104             case WRITE: {
105                 if (dto.getDataBefore() != null) {
106                     processor.processUpdatedNeutronDto((T) dto.getDataBefore(), (T) dto.getDataAfter());
107                 } else {
108                     processor.processCreatedNeutronDto((T) dto.getDataAfter());
109                 }
110                 break;
111             }
112             case SUBTREE_MODIFIED: {
113                 processor.processUpdatedNeutronDto((T) dto.getDataBefore(), (T) dto.getDataAfter());
114                 break;
115             }
116             case DELETE: {
117                 processor.processDeletedNeutronDto((T) dto.getDataBefore());
118                 break;
119             }
120         }
121     }
122
123     @VisibleForTesting
124     void clearDataChangeProviders() {
125         dataChangeProviders.clear();
126     }
127
128     @VisibleForTesting
129     <T extends DataObject> void addDataChangeProvider(MappingProvider<T> t) {
130         dataChangeProviders.add(t);
131     }
132
133     @Override
134     public void close() {
135         registeredListener.close();
136     }
137 }