/*******************************************************************************
* Copyright (c) 2015 Pivotal, Inc.
* 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:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springsource.ide.eclipse.commons.livexp.core;
import java.util.concurrent.Callable;
import org.eclipse.core.runtime.Assert;
import org.springsource.ide.eclipse.commons.livexp.Activator;
import com.google.common.collect.ImmutableSet;
/**
* This is like LiveSet / LiveSetVariable, but it can only be 'observed' not mutated.
*/
public abstract class ObservableSet<T> extends AsyncLiveExpression<ImmutableSet<T>> {
public static class Builder<T> {
private ImmutableSet<T> initialValue = ImmutableSet.of();
private AsyncMode refreshMode = AsyncMode.SYNC;
private AsyncMode eventsMode = AsyncMode.SYNC;
private Callable<ImmutableSet<T>> computer = null;
public Builder<T> events(AsyncMode eventsMode) {
this.eventsMode = eventsMode;
return this;
}
public Builder<T> refresh(AsyncMode refreshMode) {
this.refreshMode = refreshMode;
return this;
}
public ObservableSet<T> build() {
Assert.isNotNull(computer, "'compute' function must be specified");
return new ObservableSet<T>(initialValue, refreshMode, eventsMode) {
protected ImmutableSet<T> compute() {
try {
return computer.call();
} catch (Exception e) {
Activator.log(e);
return getValues();
}
}
};
}
public Builder<T> compute(Callable<ImmutableSet<T>> computer) {
this.computer = computer;
return this;
}
}
public ObservableSet() {
//Make it synch as that is 'backwards' compatible. Just in case existing code expects it.
this(ImmutableSet.<T>of(), AsyncMode.SYNC, AsyncMode.SYNC);
}
public ObservableSet(ImmutableSet<T> initialValue, AsyncMode refreshMode, AsyncMode eventsMode) {
super(initialValue, refreshMode, eventsMode);
}
public static <T> ObservableSet<T> constant(ImmutableSet<T> value) {
return new ObservableSet<T>(value, AsyncMode.SYNC, AsyncMode.SYNC) {
@Override
protected ImmutableSet<T> compute() {
return value;
}
@Override
public void addListener(ValueListener<ImmutableSet<T>> l) {
l.gotValue(this, value);
//Beyond the initial notification ... we ignore listeners... we will never notify again since
//constants can't change
}
@Override
public void removeListener(ValueListener<ImmutableSet<T>> l) {
//Ignore all listeners we will never notify anyone since
//constants can't change
}
@Override
public void syncRefresh() {
//Ignore all refreshes... no need to refresh anything since
//constants can't change
}
};
}
public ImmutableSet<T> getValues() {
return getValue();
}
public boolean contains(T e) {
return getValues().contains(e);
}
/**
* A lambda-friendly way to create a ObservableSet from a 'compute' function.
*/
public static <T> ObservableSet<T> create(Callable<ImmutableSet<T>> computer) {
Builder<T> bldr = builder();
return bldr.compute(computer).build();
}
public static <T> Builder<T> builder() {
return new Builder<T>();
}
}