/*******************************************************************************
* 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;
/**
* A basic mutable {@link Export} derived from a single dynamic {@link Import}.
*
* @author mcculls@gmail.com (Stuart McCulloch)
*/
public class SimpleExport<T>
implements Export<T> {
// track usage of the original dynamic service so we can unwind it later
private static final class CountingImport<T>
extends DelegatingImport<T> {
private int count;
CountingImport(final Import<T> service) {
super(service);
}
@Override
public T get() {
count++;
return super.get();
}
@Override
public void unget() {
count--;
super.unget();
}
void unwind() {
// service swapped while still in use, so balance the surplus of "gets"
while (count-- > 0) {
super.unget();
}
}
}
private Import<T> service;
private Map<String, ?> attributes;
/**
* Create a new {@link Export} from the given {@link Import}.
*
* @param service service being exported
*/
public SimpleExport(final Import<T> service) {
this.service = new CountingImport<T>(service);
}
public synchronized T get() {
return service.get();
}
public synchronized Map<String, ?> attributes() {
return null == attributes ? service.attributes() : attributes;
}
public synchronized void unget() {
service.unget();
}
public boolean available() {
return service.available();
}
public synchronized void put(final T newInstance) {
// might need to balance the gets + ungets
if (service instanceof CountingImport<?>) {
((CountingImport<?>) service).unwind();
}
service = new StaticImport<T>(newInstance, service.attributes());
}
public synchronized void attributes(final Map<String, ?> newAttributes) {
attributes = newAttributes;
}
public void unput() {
put(null); // simple alias
}
}