BUG-8: mark deprecated classes as such
[controller.git] / opendaylight / md-sal / sal-common-impl / src / main / java / org / opendaylight / controller / md / sal / common / impl / routing / AbstractDataReadRouter.java
1 /*
2  * Copyright (c) 2014 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 package org.opendaylight.controller.md.sal.common.impl.routing;
9
10 import java.util.Map.Entry;
11
12 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
13 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
14 import org.opendaylight.yangtools.concepts.Path;
15 import org.opendaylight.yangtools.concepts.Registration;
16
17 import com.google.common.base.Function;
18 import com.google.common.base.Predicate;
19 import com.google.common.collect.FluentIterable;
20 import com.google.common.collect.HashMultimap;
21 import com.google.common.collect.Multimap;
22 import com.google.common.collect.Multimaps;
23
24 /**
25  * Base abstract implementation of DataReadRouter, which performs
26  * a read operation on multiple data readers and then merges result.
27  *
28  * @param <P>
29  * @param <D>
30  */
31 @Deprecated
32 public abstract class AbstractDataReadRouter<P extends Path<P>, D> implements DataReader<P, D> {
33
34     Multimap<P, DataReaderRegistration<P, D>> configReaders = Multimaps.synchronizedSetMultimap(HashMultimap.<P, DataReaderRegistration<P, D>>create());
35     Multimap<P, DataReaderRegistration<P, D>> operationalReaders = Multimaps.synchronizedSetMultimap(HashMultimap.<P, DataReaderRegistration<P, D>>create());
36
37     @Override
38     public D readConfigurationData(P path) {
39         FluentIterable<D> dataBits = FluentIterable //
40                 .from(getReaders(configReaders, path)).transform(configurationRead(path));
41         return merge(path,dataBits);
42     }
43
44     @Override
45     public D readOperationalData(P path) {
46         FluentIterable<D> dataBits = FluentIterable //
47                 .from(getReaders(operationalReaders, path)).transform(operationalRead(path));
48         return merge(path,dataBits);
49
50     }
51
52     /**
53      * Merges data readed by reader instances from specified path
54      *
55      * @param path Path on which read was performed
56      * @param data Data which was returned by read operation.
57      * @return Merged result.
58      */
59     protected abstract D merge(P path,Iterable<D> data);
60
61     /**
62      * Returns a function which performs configuration read for supplied path
63      *
64      * @param path
65      * @return function which performs configuration read for supplied path
66      */
67
68     private Function<DataReader<P, D>, D> configurationRead(final P path) {
69         return new Function<DataReader<P, D>, D>() {
70             @Override
71             public D apply(DataReader<P, D> input) {
72                 return input.readConfigurationData(path);
73             }
74         };
75     }
76
77     /**
78      * Returns a function which performs operational read for supplied path
79      *
80      * @param path
81      * @return function which performs operational read for supplied path
82      */
83     private Function<DataReader<P, D>, D> operationalRead(final P path) {
84         return new Function<DataReader<P, D>, D>() {
85             @Override
86             public D apply(DataReader<P, D> input) {
87                 return input.readOperationalData(path);
88             }
89         };
90     }
91
92     // Registrations
93
94     /**
95      * Register's a reader for operational data.
96      *
97      * @param path Path which is served by this reader
98      * @param reader Reader instance which is responsible for reading particular subpath.
99      * @return
100      */
101     public Registration registerOperationalReader(P path, DataReader<P, D> reader) {
102         OperationalDataReaderRegistration<P, D> ret = new OperationalDataReaderRegistration<>(path, reader);
103         operationalReaders.put(path, ret);
104         return ret;
105     }
106
107     public Registration registerConfigurationReader(P path, DataReader<P, D> reader) {
108         ConfigurationDataReaderRegistration<P, D> ret = new ConfigurationDataReaderRegistration<>(path, reader);
109         configReaders.put(path, ret);
110         return ret;
111     }
112
113     Iterable<DataReader<P, D>> getOperationalReaders(P path) {
114         return getReaders(operationalReaders, path);
115     }
116
117     Iterable<DataReader<P, D>> getConfigurationReaders(P path) {
118         return getReaders(configReaders, path);
119     }
120
121     private Iterable<DataReader<P, D>> getReaders(Multimap<P, DataReaderRegistration<P, D>> readerMap, P path) {
122         return FluentIterable
123             .from(readerMap.entries()) //
124             .filter(affects(path)) //
125             .transform(retrieveInstance());
126     }
127
128     private void removeRegistration(OperationalDataReaderRegistration<?, ?> registration) {
129         operationalReaders.remove(registration.getKey(), registration);
130     }
131
132     private void removeRegistration(ConfigurationDataReaderRegistration<?, ?> registration) {
133         configReaders.remove(registration.getKey(), registration);
134     }
135
136     private Function<? super Entry<P, DataReaderRegistration<P, D>>, DataReader<P, D>> retrieveInstance() {
137         return new Function<Entry<P, DataReaderRegistration<P, D>>, DataReader<P,D>>() {
138             @Override
139             public DataReader<P, D> apply(Entry<P, DataReaderRegistration<P, D>> input) {
140                 return input.getValue().getInstance();
141             }
142         };
143     }
144
145     private Predicate<? super Entry<P, DataReaderRegistration<P, D>>> affects(final P path) {
146
147         return new Predicate<Entry<P, DataReaderRegistration<P, D>>>() {
148
149             @Override
150             public boolean apply(Entry<P, DataReaderRegistration<P, D>> input) {
151                 final P key = input.getKey();
152                 return key.contains(path) || ((P) path).contains(key);
153             }
154
155         };
156     }
157
158     @SuppressWarnings("hiding")
159     private class ConfigurationDataReaderRegistration<P extends Path<P>, D> extends DataReaderRegistration<P, D> {
160
161         public ConfigurationDataReaderRegistration(P key, DataReader<P, D> instance) {
162             super(key, instance);
163         }
164
165         @Override
166         protected void removeRegistration() {
167             AbstractDataReadRouter.this.removeRegistration(this);
168         }
169     }
170
171     @SuppressWarnings("hiding")
172     private class OperationalDataReaderRegistration<P extends Path<P>, D> extends DataReaderRegistration<P, D> {
173
174         public OperationalDataReaderRegistration(P key, DataReader<P, D> instance) {
175             super(key, instance);
176         }
177
178         @Override
179         protected void removeRegistration() {
180             AbstractDataReadRouter.this.removeRegistration(this);
181         }
182     }
183
184     private abstract static class DataReaderRegistration<P extends Path<P>, D> extends
185             AbstractObjectRegistration<DataReader<P, D>> {
186
187         private final P key;
188
189         public P getKey() {
190             return this.key;
191         }
192
193         public DataReaderRegistration(P key, DataReader<P, D> instance) {
194             super(instance);
195             this.key = key;
196         }
197     }
198 }