Java tutorial
/* * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ 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; import com.google.common.collect.Multimaps; /** * Base abstract implementation of DataReadRouter, which performs * a read operation on multiple data readers and then merges result. * * @param <P> * @param <D> */ @Deprecated public abstract class AbstractDataReadRouter<P extends Path<P>, D> implements DataReader<P, D> { Multimap<P, DataReaderRegistration<P, D>> configReaders = Multimaps .synchronizedSetMultimap(HashMultimap.<P, DataReaderRegistration<P, D>>create()); Multimap<P, DataReaderRegistration<P, D>> operationalReaders = Multimaps .synchronizedSetMultimap(HashMultimap.<P, DataReaderRegistration<P, D>>create()); @Override public D readConfigurationData(P path) { FluentIterable<D> dataBits = FluentIterable // .from(getReaders(configReaders, path)).transform(configurationRead(path)); return merge(path, dataBits); } @Override public D readOperationalData(P path) { FluentIterable<D> 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<D> data); /** * Returns a function which performs configuration read for supplied path * * @param path * @return function which performs configuration read for supplied path */ private Function<DataReader<P, D>, D> configurationRead(final P path) { return new Function<DataReader<P, D>, D>() { @Override public D apply(DataReader<P, D> 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<DataReader<P, D>, D> operationalRead(final P path) { return new Function<DataReader<P, D>, D>() { @Override public D apply(DataReader<P, D> 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<P, D> reader) { OperationalDataReaderRegistration<P, D> ret = new OperationalDataReaderRegistration<>(path, reader); operationalReaders.put(path, ret); return ret; } public Registration registerConfigurationReader(P path, DataReader<P, D> reader) { ConfigurationDataReaderRegistration<P, D> ret = new ConfigurationDataReaderRegistration<>(path, reader); configReaders.put(path, ret); return ret; } Iterable<DataReader<P, D>> getOperationalReaders(P path) { return getReaders(operationalReaders, path); } Iterable<DataReader<P, D>> getConfigurationReaders(P path) { return getReaders(configReaders, path); } private Iterable<DataReader<P, D>> getReaders(Multimap<P, DataReaderRegistration<P, D>> 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<? super Entry<P, DataReaderRegistration<P, D>>, DataReader<P, D>> retrieveInstance() { return new Function<Entry<P, DataReaderRegistration<P, D>>, DataReader<P, D>>() { @Override public DataReader<P, D> apply(Entry<P, DataReaderRegistration<P, D>> input) { return input.getValue().getInstance(); } }; } private Predicate<? super Entry<P, DataReaderRegistration<P, D>>> affects(final P path) { return new Predicate<Entry<P, DataReaderRegistration<P, D>>>() { @Override public boolean apply(Entry<P, DataReaderRegistration<P, D>> input) { final P key = input.getKey(); return key.contains(path) || ((P) path).contains(key); } }; } @SuppressWarnings("hiding") private class ConfigurationDataReaderRegistration<P extends Path<P>, D> extends DataReaderRegistration<P, D> { public ConfigurationDataReaderRegistration(P key, DataReader<P, D> instance) { super(key, instance); } @Override protected void removeRegistration() { AbstractDataReadRouter.this.removeRegistration(this); } } @SuppressWarnings("hiding") private class OperationalDataReaderRegistration<P extends Path<P>, D> extends DataReaderRegistration<P, D> { public OperationalDataReaderRegistration(P key, DataReader<P, D> instance) { super(key, instance); } @Override protected void removeRegistration() { AbstractDataReadRouter.this.removeRegistration(this); } } private abstract static class DataReaderRegistration<P extends Path<P>, D> extends AbstractObjectRegistration<DataReader<P, D>> { private final P key; public P getKey() { return this.key; } public DataReaderRegistration(P key, DataReader<P, D> instance) { super(instance); this.key = key; } } }