/*******************************************************************************
* 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.internal;
import java.util.Map;
import org.eclipse.sisu.peaberry.Export;
import org.eclipse.sisu.peaberry.Import;
import org.eclipse.sisu.peaberry.ServiceWatcher;
import org.eclipse.sisu.peaberry.builders.ImportDecorator;
import org.eclipse.sisu.peaberry.util.DelegatingImport;
import org.eclipse.sisu.peaberry.util.SimpleExport;
/**
* A {@link ServiceWatcher} decorated by the given {@link ImportDecorator}.
*
* @author mcculls@gmail.com (Stuart McCulloch)
*/
final class DecoratedServiceWatcher<S>
implements ServiceWatcher<S> {
private final ImportDecorator<? super S> decorator;
private final ServiceWatcher<? super S> watcher;
DecoratedServiceWatcher(final ImportDecorator<? super S> decorator,
final ServiceWatcher<? super S> watcher) {
this.decorator = decorator;
this.watcher = watcher;
}
public <T extends S> Export<T> add(final Import<T> service) {
// wrap service to allow updates, decorate the wrapper, then publish
final Export<T> original = new SimpleExport<T>(service);
final Import<T> decorated = decorator.decorate(original);
final Export<T> published = watcher.add(decorated);
// watcher is not interested!
if (null == published) {
return null;
}
return new DecoratedExport<T>(original, decorated, published);
}
private static final class DecoratedExport<T>
extends DelegatingImport<T>
implements Export<T> {
private final Export<T> original;
private final Import<T> decorated;
private final Export<T> published;
DecoratedExport(final Export<T> original, final Import<T> decorated, final Export<T> published) {
super(original);
this.original = original;
this.decorated = decorated;
this.published = published;
}
public synchronized void put(final T newInstance) {
// force decoration of new instance
original.put(newInstance);
published.put(null == newInstance ? null : decorated.get());
}
public synchronized void attributes(final Map<String, ?> attributes) {
// force decoration of new attributes
original.attributes(attributes);
published.attributes(decorated.attributes());
}
public void unput() {
put(null); // simple alias
}
}
@Override
public boolean equals(final Object rhs) {
if (rhs instanceof DecoratedServiceWatcher<?>) {
final DecoratedServiceWatcher<?> decoratedWatcher = (DecoratedServiceWatcher<?>) rhs;
return decorator.equals(decoratedWatcher.decorator)
&& watcher.equals(decoratedWatcher.watcher);
}
return false;
}
@Override
public int hashCode() {
return decorator.hashCode() ^ watcher.hashCode();
}
}