/** * Reverses the operations detailed in the list of deltas on the given wavelet. * * @param wavelet {@link ObservableWaveletData} to apply operations to * @param deltas the {@link WaveletDelta} containing the operations which we should revert on the * given wavelet. * @throws OperationException if the operations can not be rolled back. */ private static void rollback(ObservableWaveletData wavelet, List<TransformedWaveletDelta> deltas) throws OperationException { List<WaveletOperation> inverseOps = Lists.newArrayList(); // Go through everything in reverse order for (int i = deltas.size() - 1; i >= 0; i--) { TransformedWaveletDelta delta = deltas.get(i); // Metadata such as the last modified ts will change due to the rollback // of operations. for (int j = delta.size() - 1; j >= 0; j--) { WaveletOperation op = delta.get(j); WaveletOperation inverseOp = WaveletOperationInverter.invert(op); inverseOps.add(inverseOp); } } long startVersion = wavelet.getVersion(); int opCount = 0; for (WaveletOperation inverseOp : inverseOps) { inverseOp.apply(wavelet); opCount++; } if (wavelet.getVersion() != startVersion - opCount) { throw new OperationException( "Expected end version " + (startVersion - opCount) + " doesn't match the version of the wavelet " + wavelet.getVersion()); } }
/** Opens a mux, binding its operation channels with operation-supporting wavelets. */ public static void openAndBind( WaveletOperationalizer operationalizer, WaveViewImpl<OpBasedWavelet> wave, WaveDocuments<? extends CcDocument> docRegistry, OperationChannelMultiplexer mux, IdFilter filter, Command whenOpened) { StaticChannelBinder staticBinder = new StaticChannelBinder(operationalizer, docRegistry); LiveChannelBinder liveBinder = new LiveChannelBinder(staticBinder, operationalizer, wave, mux, whenOpened); final Collection<KnownWavelet> remoteWavelets = CollectionUtils.createQueue(); final Collection<ObservableWaveletData> localWavelets = CollectionUtils.createQueue(); for (ObservableWaveletData wavelet : operationalizer.getWavelets()) { // Version 0 wavelets must be wavelets that the client has created in this // session. They are not to be included in the known-wavelet collection, // because the server does not know about them. if (wavelet.getVersion() > 0) { remoteWavelets.add( new KnownWavelet(wavelet, wavelet.getHashedVersion(), Accessibility.READ_WRITE)); } else { localWavelets.add(wavelet); } } // Start listening to wave events and channel events. wave.addListener(liveBinder); // This binder only starts getting events once open() has been called, since // that is what sets this binder as a mux listener. Since wavelet-to-channel // binding occurs through event callbacks, this listener setting must occur // before trying to bind localWavelets. mux.open(liveBinder, filter, remoteWavelets); for (ObservableWaveletData local : localWavelets) { mux.createOperationChannel(local.getWaveletId(), local.getCreator()); } }