Package org.waveprotocol.box.server.robots.passive

Source Code of org.waveprotocol.box.server.robots.passive.WaveletOperationInverter$BlipOperationInverter

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.waveprotocol.box.server.robots.passive;

import org.waveprotocol.wave.model.document.operation.algorithm.DocOpInverter;
import org.waveprotocol.wave.model.operation.wave.AddParticipant;
import org.waveprotocol.wave.model.operation.wave.BlipContentOperation;
import org.waveprotocol.wave.model.operation.wave.BlipOperation;
import org.waveprotocol.wave.model.operation.wave.BlipOperationVisitor;
import org.waveprotocol.wave.model.operation.wave.NoOp;
import org.waveprotocol.wave.model.operation.wave.RemoveParticipant;
import org.waveprotocol.wave.model.operation.wave.SubmitBlip;
import org.waveprotocol.wave.model.operation.wave.VersionUpdateOp;
import org.waveprotocol.wave.model.operation.wave.WaveletBlipOperation;
import org.waveprotocol.wave.model.operation.wave.WaveletOperation;
import org.waveprotocol.wave.model.operation.wave.WaveletOperationContext;
import org.waveprotocol.wave.model.operation.wave.WaveletOperationVisitor;

/**
* Approximately inverts an applied wavelet operation.
*
* The only contract this inverter provides is that:
*
* <pre class="code">invert(o) ; o == id </pre>
*
* i.e., given any state {@code s} that was reached by an operation {@code o},
* the "previous" state {@code s'} can be constructed {@code s' = invert(o)(s)}
* such that applying {@code o} to it will return to the given state {@code s}.
*
* This inverter does not accept operations that do not appear in a wavelet's
* history (e.g., {@link VersionUpdateOp}).
*
* TODO(anorth): Move to {@link org.waveprotocol.wave.model.operation.wave}.
*
* @author hearnden@google.com (David Hearnden)
*/
final class WaveletOperationInverter implements WaveletOperationVisitor {

  /**
   * Inverts a blip operation, ignoring metadata.
   */
  final static class BlipOperationInverter implements BlipOperationVisitor {
    private final WaveletOperationContext reverseContext;
    private BlipOperation inverse;

    BlipOperationInverter(WaveletOperationContext reverseContext) {
      this.reverseContext = reverseContext;
    }

    static BlipOperation invert(WaveletOperationContext reverseContext, BlipOperation op) {
      return new BlipOperationInverter(reverseContext).visit(op);
    }

    private BlipOperation visit(BlipOperation op) {
      op.acceptVisitor(this);
      return inverse;
    }

    @Override
    public void visitBlipContentOperation(BlipContentOperation op) {
      inverse = new BlipContentOperation(reverseContext, DocOpInverter.invert(op.getContentOp()));
    }

    @Override
    public void visitSubmitBlip(SubmitBlip op) {
      inverse = new SubmitBlip(reverseContext);
    }
  }

  private final WaveletOperationContext reverseContext;
  private WaveletOperation inverse;

  WaveletOperationInverter(WaveletOperationContext reverseContext) {
    this.reverseContext = reverseContext;
  }

  /**
   * Inverts an operation.
   */
  static WaveletOperation invert(WaveletOperation op) {
    WaveletOperationContext forwardContext = op.getContext();
    WaveletOperationContext reverseContext = new WaveletOperationContext( //
        forwardContext.getCreator(),
        // Lie, and keep the same modification time.
        forwardContext.getTimestamp(),
        // Correctly invert the version increment.
        -forwardContext.getVersionIncrement(),
        // Lie again, and report the hashed version as the same as after op.
        // This makes it out of sync with the version number.
        forwardContext.getHashedVersion());
    return new WaveletOperationInverter(reverseContext).visit(op);
  }

  private WaveletOperation visit(WaveletOperation op) {
    op.acceptVisitor(this);
    return inverse;
  }

  @Override
  public void visitWaveletBlipOperation(WaveletBlipOperation op) {
    inverse = new WaveletBlipOperation(
        op.getBlipId(), BlipOperationInverter.invert(reverseContext, op.getBlipOp()));
  }

  @Override
  public void visitVersionUpdateOp(VersionUpdateOp op) {
    throw new UnsupportedOperationException();
  }

  @Override
  public void visitAddParticipant(AddParticipant op) {
    inverse = new RemoveParticipant(reverseContext, op.getParticipantId());
  }

  @Override
  public void visitRemoveParticipant(RemoveParticipant op) {
    inverse = new AddParticipant(reverseContext, op.getParticipantId());
  }

  @Override
  public void visitNoOp(NoOp op) {
    inverse = new NoOp(reverseContext);
  }
}
TOP

Related Classes of org.waveprotocol.box.server.robots.passive.WaveletOperationInverter$BlipOperationInverter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.