2 * Copyright (c) 2014 Cisco Systems, Inc. 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
8 package org.opendaylight.controller.md.sal.common.impl.routing;
10 import java.util.Map.Entry;
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;
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;
25 * Base abstract implementation of DataReadRouter, which performs
26 * a read operation on multiple data readers and then merges result.
31 public abstract class AbstractDataReadRouter<P extends Path<P>, D> implements DataReader<P, D> {
33 Multimap<P, DataReaderRegistration<P, D>> configReaders = Multimaps.synchronizedSetMultimap(HashMultimap.<P, DataReaderRegistration<P, D>>create());
34 Multimap<P, DataReaderRegistration<P, D>> operationalReaders = Multimaps.synchronizedSetMultimap(HashMultimap.<P, DataReaderRegistration<P, D>>create());
37 public D readConfigurationData(P path) {
38 FluentIterable<D> dataBits = FluentIterable //
39 .from(getReaders(configReaders, path)).transform(configurationRead(path));
40 return merge(path,dataBits);
44 public D readOperationalData(P path) {
45 FluentIterable<D> dataBits = FluentIterable //
46 .from(getReaders(operationalReaders, path)).transform(operationalRead(path));
47 return merge(path,dataBits);
52 * Merges data readed by reader instances from specified path
54 * @param path Path on which read was performed
55 * @param data Data which was returned by read operation.
56 * @return Merged result.
58 protected abstract D merge(P path,Iterable<D> data);
61 * Returns a function which performs configuration read for supplied path
64 * @return function which performs configuration read for supplied path
67 private Function<DataReader<P, D>, D> configurationRead(final P path) {
68 return new Function<DataReader<P, D>, D>() {
70 public D apply(DataReader<P, D> input) {
71 return input.readConfigurationData(path);
77 * Returns a function which performs operational read for supplied path
80 * @return function which performs operational read for supplied path
82 private Function<DataReader<P, D>, D> operationalRead(final P path) {
83 return new Function<DataReader<P, D>, D>() {
85 public D apply(DataReader<P, D> input) {
86 return input.readOperationalData(path);
94 * Register's a reader for operational data.
96 * @param path Path which is served by this reader
97 * @param reader Reader instance which is responsible for reading particular subpath.
100 public Registration<DataReader<P, D>> registerOperationalReader(P path, DataReader<P, D> reader) {
101 OperationalDataReaderRegistration<P, D> ret = new OperationalDataReaderRegistration<>(path, reader);
102 operationalReaders.put(path, ret);
106 public Registration<DataReader<P, D>> registerConfigurationReader(P path, DataReader<P, D> reader) {
107 ConfigurationDataReaderRegistration<P, D> ret = new ConfigurationDataReaderRegistration<>(path, reader);
108 configReaders.put(path, ret);
112 Iterable<DataReader<P, D>> getOperationalReaders(P path) {
113 return getReaders(operationalReaders, path);
116 Iterable<DataReader<P, D>> getConfigurationReaders(P path) {
117 return getReaders(configReaders, path);
120 private Iterable<DataReader<P, D>> getReaders(Multimap<P, DataReaderRegistration<P, D>> readerMap, P path) {
121 return FluentIterable
122 .from(readerMap.entries()) //
123 .filter(affects(path)) //
124 .transform(retrieveInstance());
127 private void removeRegistration(OperationalDataReaderRegistration<?, ?> registration) {
128 operationalReaders.remove(registration.getKey(), registration);
131 private void removeRegistration(ConfigurationDataReaderRegistration<?, ?> registration) {
132 configReaders.remove(registration.getKey(), registration);
135 private Function<? super Entry<P, DataReaderRegistration<P, D>>, DataReader<P, D>> retrieveInstance() {
136 return new Function<Entry<P, DataReaderRegistration<P, D>>, DataReader<P,D>>() {
138 public DataReader<P, D> apply(Entry<P, DataReaderRegistration<P, D>> input) {
139 return input.getValue().getInstance();
144 private Predicate<? super Entry<P, DataReaderRegistration<P, D>>> affects(final P path) {
146 return new Predicate<Entry<P, DataReaderRegistration<P, D>>>() {
149 public boolean apply(Entry<P, DataReaderRegistration<P, D>> input) {
150 final P key = input.getKey();
151 return key.contains(path) || ((P) path).contains(key);
157 @SuppressWarnings("hiding")
158 private class ConfigurationDataReaderRegistration<P extends Path<P>, D> extends DataReaderRegistration<P, D> {
160 public ConfigurationDataReaderRegistration(P key, DataReader<P, D> instance) {
161 super(key, instance);
165 protected void removeRegistration() {
166 AbstractDataReadRouter.this.removeRegistration(this);
170 @SuppressWarnings("hiding")
171 private class OperationalDataReaderRegistration<P extends Path<P>, D> extends DataReaderRegistration<P, D> {
173 public OperationalDataReaderRegistration(P key, DataReader<P, D> instance) {
174 super(key, instance);
178 protected void removeRegistration() {
179 AbstractDataReadRouter.this.removeRegistration(this);
183 private abstract static class DataReaderRegistration<P extends Path<P>, D> extends
184 AbstractObjectRegistration<DataReader<P, D>> {
192 public DataReaderRegistration(P key, DataReader<P, D> instance) {