/**
* Copyright 2014 Comcast Cable Communications Management, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.comcast.viper.flume2storm.location;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
/**
* Implements the methods to deal with ServiceListener.
*
* @param <SP>
* The Service Provider class
*/
public abstract class AbstractLocationService<SP extends ServiceProvider<?>> implements LocationService<SP> {
/*
* Access to the methods to add and remove listeners is synchronized so that
* building the immutable list of service providers is thread-safe. This is a
* small price to pay (as it should not occur too often) so that future access
* to the list is direct atomic reference to the immutable list.
*/
protected final AtomicReference<List<ServiceListener<SP>>> listeners;
protected final ServiceListener<SP> managerListener;
protected final ServiceProviderManager<SP> serviceProviderManager;
/**
* This {@link ServiceListener} gets the notifications from the
* {@link ServiceProviderManager} and dispatches it to the registered
* listeners
*/
private class MainServiceListener implements ServiceListener<SP> {
private final Logger LOG = LoggerFactory.getLogger(MainServiceListener.class);
protected MainServiceListener() {
super(); // To avoid synthetic accessor method
}
/**
* @see com.comcast.viper.flume2storm.location.ServiceListener#onProviderAdded(com.comcast.viper.flume2storm.location.ServiceProvider)
*/
public void onProviderAdded(SP serviceProvider) {
for (final ServiceListener<SP> l : listeners.get()) {
try {
l.onProviderAdded(serviceProvider);
} catch (Exception e) {
LOG.warn("Failed to notify listeners about the addition of service provider {} : {}", serviceProvider,
e.getLocalizedMessage());
}
}
}
/**
* @see com.comcast.viper.flume2storm.location.ServiceListener#onProviderRemoved(com.comcast.viper.flume2storm.location.ServiceProvider)
*/
public void onProviderRemoved(SP serviceProvider) {
for (final ServiceListener<SP> l : listeners.get()) {
try {
l.onProviderRemoved(serviceProvider);
} catch (Exception e) {
LOG.warn("Failed to notify listeners about the removal of service provider {} : {}", serviceProvider,
e.getLocalizedMessage());
}
}
}
}
protected AbstractLocationService() {
listeners = new AtomicReference<List<ServiceListener<SP>>>(new ArrayList<ServiceListener<SP>>());
managerListener = new MainServiceListener();
serviceProviderManager = new ServiceProviderManager<SP>(managerListener);
}
/**
* @see com.comcast.viper.flume2storm.location.LocationService#addListener(com.comcast.viper.flume2storm.location.ServiceListener)
*/
public synchronized final void addListener(ServiceListener<SP> listener) {
List<ServiceListener<SP>> oldList = listeners.get();
Builder<ServiceListener<SP>> builder = new Builder<ServiceListener<SP>>();
builder.addAll(oldList);
builder.add(listener);
listeners.getAndSet(builder.build());
for (SP serviceProvider : serviceProviderManager.get()) {
listener.onProviderAdded(serviceProvider);
}
}
/**
* @see com.comcast.viper.flume2storm.location.LocationService#removeListener(com.comcast.viper.flume2storm.location.ServiceListener)
*/
public synchronized final void removeListener(ServiceListener<SP> listener) {
List<ServiceListener<SP>> oldList = new ArrayList<ServiceListener<SP>>(listeners.get());
oldList.remove(listener);
listeners.getAndSet(ImmutableList.copyOf(oldList));
}
/**
* @see com.comcast.viper.flume2storm.location.LocationService#getServiceProviders()
*/
@Override
public List<SP> getServiceProviders() {
return serviceProviderManager.get();
}
/**
* @see com.comcast.viper.flume2storm.location.LocationService#containsServiceProvider(com.comcast.viper.flume2storm.location.ServiceProvider)
*/
@Override
public boolean containsServiceProvider(SP serviceProvider) {
return serviceProviderManager.contains(serviceProvider.getConnectionParameters().getId());
}
/**
* @see com.comcast.viper.flume2storm.location.LocationService#containsServiceProvider(java.lang.String)
*/
@Override
public boolean containsServiceProvider(String serviceProviderId) {
return serviceProviderManager.contains(serviceProviderId);
}
}