package org.swellrt.client;
import java.util.Set;
import org.waveprotocol.box.webclient.client.RemoteViewServiceMultiplexer;
import org.waveprotocol.wave.client.account.ProfileManager;
import org.waveprotocol.wave.client.common.util.AsyncHolder;
import org.waveprotocol.wave.client.common.util.AsyncHolder.Accessor;
import org.waveprotocol.wave.client.wave.InteractiveDocument;
import org.waveprotocol.wave.client.wave.WaveDocuments;
import org.waveprotocol.wave.concurrencycontrol.common.UnsavedDataListener;
import org.waveprotocol.wave.model.id.IdGenerator;
import org.waveprotocol.wave.model.wave.ParticipantId;
import org.waveprotocol.wave.model.wave.opbased.ObservableWaveView;
import org.waveprotocol.wave.model.waveref.WaveRef;
/**
* The Wave Loader encapsulates the process of loading a Wave and Wavelets from
* the server and build the in-memory structure.
*
* It uses the original stage-based load process optimized for browsers and the
* conversational model. TODO consider to simplify the staged loader.
*
* Use the method {@link Stages#load} to launch the load process.
*
* @author pablojan@gmail.com (Pablo Ojanguren)
*
*/
public class WaveLoader extends Stages {
private final static AsyncHolder<Object> HALT = new AsyncHolder<Object>() {
@Override
public void call(Accessor<Object> accessor) {
// Never ready, so never notify the accessor.
}
};
protected boolean closed;
private StageOne one;
private StageTwo two;
private StageThree three;
protected ObservableWaveView wave;
protected WaveRef waveRef;
private RemoteViewServiceMultiplexer channel;
protected IdGenerator idGenerator;
private ProfileManager profileManager;
protected String localDomain;
protected Set<ParticipantId> participants;
protected boolean isNewWave;
private UnsavedDataListener dataListener;
protected ParticipantId loggedInUser;
public WaveLoader(WaveRef waveRef, RemoteViewServiceMultiplexer channel,
IdGenerator idGenerator, String localDomain,
Set<ParticipantId> participants, ParticipantId loggedInUser,
UnsavedDataListener dataListener) {
super();
this.waveRef = waveRef;
this.channel = channel;
this.idGenerator = idGenerator;
this.localDomain = localDomain;
this.participants = participants;
this.loggedInUser = loggedInUser;
this.dataListener = dataListener;
}
//
// Stages staff
//
@Override
protected AsyncHolder<StageZero> createStageZeroLoader() {
return haltIfClosed(super.createStageZeroLoader());
}
@Override
protected AsyncHolder<StageOne> createStageOneLoader(StageZero zero) {
return haltIfClosed(new StageOne.DefaultProvider(zero) {});
}
@Override
protected AsyncHolder<StageTwo> createStageTwoLoader(StageOne one) {
return haltIfClosed(new StageTwoProvider(this.one = one, this.waveRef, this.channel,
this.isNewWave, this.idGenerator, this.dataListener,
this.participants));
}
@Override
protected AsyncHolder<StageThree> createStageThreeLoader(final StageTwo two) {
return haltIfClosed(new StageThree.DefaultProvider(this.two = two) {
@Override
protected void create(final Accessor<StageThree> whenReady) {
// Prepend an init wave flow onto the stage continuation.
super.create(new Accessor<StageThree>() {
@Override
public void use(StageThree x) {
onStageThreeLoaded(x, whenReady);
}
});
}
@Override
protected String getLocalDomain() {
return WaveLoader.this.localDomain;
}
});
}
private void onStageThreeLoaded(StageThree x, Accessor<StageThree> whenReady) {
if (closed) {
// Stop the loading process.
return;
}
three = x;
wave = two.getWave();
// Add into some Wave store?
install();
whenReady.use(x);
}
/**
* A hook to install features that are not dependent an a certain stage.
*/
protected void install() {
// WindowTitleHandler.install(context.getStore(), context.getWaveFrame());
}
public void destroy() {
if (wave != null) {
// Remove from some wave store
wave = null;
}
if (three != null) {
// e.g. three.getEditActions().stopEditing();
three = null;
}
if (two != null) {
two.getConnector().close();
two = null;
}
if (one != null) {
// e.g. one.getWavePanel().destroy();
one = null;
}
closed = true;
}
/**
* @return a halting provider if this stage is closed. Otherwise, returns the
* given provider.
*/
@SuppressWarnings("unchecked")
// HALT is safe as a holder for any type
private <T> AsyncHolder<T> haltIfClosed(AsyncHolder<T> provider) {
return closed ? (AsyncHolder<T>) HALT : provider;
}
public ObservableWaveView getWave() {
return wave;
}
public String getLocalDomain() {
return localDomain;
}
public boolean isNewWave() {
return isNewWave;
}
public ParticipantId getLoggedInUser() {
return loggedInUser;
}
public IdGenerator getIdGenerator() {
return idGenerator;
}
public WaveDocuments<? extends InteractiveDocument> getDocumentRegistry() {
return two.getDocumentRegistry();
}
public boolean isClosed() {
return closed;
}
}