package org.opendaylight.controller.md.sal.common.impl.routing; import java.util.Map.Entry; import org.opendaylight.controller.md.sal.common.api.data.DataReader; import org.opendaylight.yangtools.concepts.AbstractObjectRegistration; import org.opendaylight.yangtools.concepts.Path; import org.opendaylight.yangtools.concepts.Registration; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.FluentIterable; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; /** * Base abstract implementation of DataReadRouter, which performs * a read operation on multiple data readers and then merges result. * * @param

* @param */ public abstract class AbstractDataReadRouter

, D> implements DataReader { Multimap> configReaders = HashMultimap.create(); Multimap> operationalReaders = HashMultimap.create(); @Override public D readConfigurationData(P path) { FluentIterable dataBits = FluentIterable // .from(getReaders(configReaders, path)).transform(configurationRead(path)); return merge(path,dataBits); } @Override public D readOperationalData(P path) { FluentIterable dataBits = FluentIterable // .from(getReaders(operationalReaders, path)).transform(operationalRead(path)); return merge(path,dataBits); } /** * Merges data readed by reader instances from specified path * * @param path Path on which read was performed * @param data Data which was returned by read operation. * @return Merged result. */ protected abstract D merge(P path,Iterable data); /** * Returns a function which performs configuration read for supplied path * * @param path * @return function which performs configuration read for supplied path */ private Function, D> configurationRead(final P path) { return new Function, D>() { @Override public D apply(DataReader input) { return input.readConfigurationData(path); } }; } /** * Returns a function which performs operational read for supplied path * * @param path * @return function which performs operational read for supplied path */ private Function, D> operationalRead(final P path) { return new Function, D>() { @Override public D apply(DataReader input) { return input.readOperationalData(path); } }; } // Registrations /** * Register's a reader for operational data. * * @param path Path which is served by this reader * @param reader Reader instance which is responsible for reading particular subpath. * @return */ public Registration> registerOperationalReader(P path, DataReader reader) { OperationalDataReaderRegistration ret = new OperationalDataReaderRegistration<>(path, reader); operationalReaders.put(path, ret); return ret; } public Registration> registerConfigurationReader(P path, DataReader reader) { ConfigurationDataReaderRegistration ret = new ConfigurationDataReaderRegistration<>(path, reader); configReaders.put(path, ret); return ret; } Iterable> getOperationalReaders(P path) { return getReaders(operationalReaders, path); } Iterable> getConfigurationReaders(P path) { return getReaders(configReaders, path); } private Iterable> getReaders(Multimap> readerMap, P path) { return FluentIterable .from(readerMap.entries()) // .filter(affects(path)) // .transform(retrieveInstance()); } private void removeRegistration(OperationalDataReaderRegistration registration) { operationalReaders.remove(registration.getKey(), registration); } private void removeRegistration(ConfigurationDataReaderRegistration registration) { configReaders.remove(registration.getKey(), registration); } private Function>, DataReader> retrieveInstance() { return new Function>, DataReader>() { @Override public DataReader apply(Entry> input) { return input.getValue().getInstance(); } }; } private Predicate>> affects(final P path) { return new Predicate>>() { @Override public boolean apply(Entry> input) { final Path key = input.getKey(); return key.contains(path) || ((Path) path).contains(key); } }; } private class ConfigurationDataReaderRegistration

, D> extends DataReaderRegistration { public ConfigurationDataReaderRegistration(P key, DataReader instance) { super(key, instance); } @Override protected void removeRegistration() { AbstractDataReadRouter.this.removeRegistration(this); } } private class OperationalDataReaderRegistration

, D> extends DataReaderRegistration { public OperationalDataReaderRegistration(P key, DataReader instance) { super(key, instance); } @Override protected void removeRegistration() { AbstractDataReadRouter.this.removeRegistration(this); } } private abstract static class DataReaderRegistration

, D> extends AbstractObjectRegistration> { private final P key; public P getKey() { return this.key; } public DataReaderRegistration(P key, DataReader instance) { super(instance); this.key = key; } } }