2 * Copyright (c) 2015 CableLabs and others. All rights reserved.
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
9 package org.opendaylight.controller.packetcable.provider;
11 import static com.google.common.base.Preconditions.checkNotNull;
12 import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.collectTypeFromMap;
13 import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.collectTypeFromSet;
14 import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.logChange;
15 import static org.opendaylight.controller.packetcable.provider.DataChangeUtils.relativeComplement;
17 import com.google.common.collect.Maps;
20 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
21 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
22 import org.opendaylight.yangtools.yang.binding.DataObject;
23 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
30 public abstract class AbstractDataChangeListener<T extends DataObject> implements DataChangeListener {
32 protected final Logger logger = LoggerFactory.getLogger(getClass());
34 private final Class<T> tClass;
36 public AbstractDataChangeListener(Class<T> tClass) {
37 this.tClass = checkNotNull(tClass);
41 public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> asyncDataChangeEvent) {
42 logger.debug("############{}.onDataChanged()", getClass().getSimpleName());
43 logChange(logger, asyncDataChangeEvent);
45 final Map<InstanceIdentifier<?>, DataObject> allCreatedData = asyncDataChangeEvent.getCreatedData();
46 final Map<InstanceIdentifier<?>, DataObject> allOriginalData = asyncDataChangeEvent.getOriginalData();
47 final Map<InstanceIdentifier<?>, DataObject> allUpdatedData = asyncDataChangeEvent.getUpdatedData();
49 // UpdatedData also contains all data that was created, remove it to get the set of only updated data
50 final Map<InstanceIdentifier<?>, DataObject> trueUpdatedData =
51 relativeComplement(allCreatedData, allUpdatedData);
52 final Map<InstanceIdentifier<?>, DataObject> trueOriginalData =
53 relativeComplement(allCreatedData, allOriginalData);
55 if (!allCreatedData.isEmpty()) {
56 final Map<InstanceIdentifier<T>, T> createdTs = collectTypeFromMap(tClass, allCreatedData);
58 if (createdTs.isEmpty()) {
59 // this should not happen since this object only listens for changes in one tree
60 logger.warn("Expected created {}(s) but none were found: {}", tClass.getSimpleName(), allCreatedData);
63 handleCreatedData(createdTs);
67 if (!trueUpdatedData.isEmpty()) {
68 final Map<InstanceIdentifier<T>, T> updatedTs = collectTypeFromMap(tClass, trueUpdatedData);
69 if (updatedTs.isEmpty()) {
70 // this should not happen since this object should only listen for changes in its tree
71 logger.warn("Expected updated {}(s) but none were found: {}", tClass.getSimpleName(), trueUpdatedData);
75 final Map<InstanceIdentifier<T>, T> originalTs = collectTypeFromMap(tClass, trueOriginalData);
76 for (InstanceIdentifier<T> iid : updatedTs.keySet()) {
77 if (!originalTs.containsKey(iid)) {
78 logger.warn("No original data for updated object {}", iid);
82 handleUpdatedData(updatedTs, originalTs);
86 final Set<InstanceIdentifier<?>> allRemovedPaths = asyncDataChangeEvent.getRemovedPaths();
87 if (!allRemovedPaths.isEmpty()) {
88 final Set<InstanceIdentifier<T>> removedTPaths = collectTypeFromSet(tClass, allRemovedPaths);
89 if (removedTPaths.isEmpty()) {
90 // this should not happen since this object should only listen for changes in its tree
91 logger.warn("Expected removed {} but none were found: {}", tClass.getSimpleName(), allRemovedPaths);
94 Map<InstanceIdentifier<T>, T> originalTData = Maps.newHashMapWithExpectedSize(removedTPaths.size());
95 for (InstanceIdentifier<T> iid : removedTPaths) {
96 if (allOriginalData.containsKey(iid)) {
98 originalTData.put(iid, (T) allOriginalData.get(iid));
102 handleRemovedData(removedTPaths, originalTData);
106 protected abstract void handleCreatedData(final Map<InstanceIdentifier<T>, T> createdData);
108 protected abstract void handleUpdatedData(final Map<InstanceIdentifier<T>, T> updatedData,
109 final Map<InstanceIdentifier<T>, T> originalData);
111 protected abstract void handleRemovedData(final Set<InstanceIdentifier<T>> removedPaths,
112 final Map<InstanceIdentifier<T>, T> originalData);