/*******************************************************************************
* Copyright (c) 2008, 2014 Stuart McCulloch
* 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
*
* Contributors:
* Stuart McCulloch - initial API and implementation
*******************************************************************************/
package org.eclipse.sisu.peaberry.util;
import java.util.Map;
import org.eclipse.sisu.peaberry.Export;
import org.eclipse.sisu.peaberry.Import;
import org.eclipse.sisu.peaberry.ServiceWatcher;
/**
* Skeletal implementation to simplify development of {@link ServiceWatcher}s.
* <p>
* Developers only have to extend this class and provide implementations of the
* {@link #adding(Import)}, {@link #modified(Object, Map)}, and {@link #removed}
* service tracking methods. The design of this helper class is loosely based on
* the OSGi ServiceTrackerCustomizer.
*
* @author mcculls@gmail.com (Stuart McCulloch)
*
* @since 1.1
*/
public abstract class AbstractWatcher<S>
implements ServiceWatcher<S> {
@SuppressWarnings("unchecked")
public final <T extends S> Export<T> add(final Import<T> service) {
final TrackingExport export = new TrackingExport((Import) service);
return null == export.tracker ? null : (Export) export;
}
private final class TrackingExport
extends SimpleExport<S> {
S tracker; // customized tracker object
TrackingExport(final Import<S> service) {
super(service);
tracker = adding(this);
}
@Override
public synchronized void put(final S newInstance) {
if (null != tracker) {
removed(tracker);
tracker = null;
}
super.put(newInstance);
if (null != newInstance) {
tracker = adding(this);
}
}
@Override
public synchronized void attributes(final Map<String, ?> newAttributes) {
super.attributes(newAttributes);
if (null != tracker) {
modified(tracker, newAttributes);
}
}
}
/**
* Notification that a service has been added to this watcher.
*
* @param service new service handle
* @return tracking instance, null if the service shouldn't be tracked
*/
protected S adding(final Import<S> service) {
return service.get();
}
/**
* Notification that some service attributes have been modified.
*
* @param instance tracking instance
* @param attributes service attributes
*/
protected void modified(final S instance, final Map<String, ?> attributes) {} // NOPMD
/**
* Notification that a service has been removed from this watcher.
*
* @param instance tracking instance
*/
protected void removed(final S instance) {} // NOPMD
}