Package com.google.walkaround.wave.server.model

Source Code of com.google.walkaround.wave.server.model.WaveObjectStoreModel

/*
* Copyright 2011 Google Inc. All Rights Reserved.
*
* Licensed 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 com.google.walkaround.wave.server.model;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.google.walkaround.slob.shared.ChangeData;
import com.google.walkaround.slob.shared.ChangeRejected;
import com.google.walkaround.slob.shared.InvalidSnapshot;
import com.google.walkaround.slob.shared.MessageException;
import com.google.walkaround.slob.shared.SlobModel;
import com.google.walkaround.wave.shared.IdHack;
import com.google.walkaround.wave.shared.MessageSerializer;
import com.google.walkaround.wave.shared.WaveSerializer;
import com.google.walkaround.wave.shared.WaveletUtil;

import org.waveprotocol.wave.model.operation.OperationException;
import org.waveprotocol.wave.model.operation.OperationPair;
import org.waveprotocol.wave.model.operation.TransformException;
import org.waveprotocol.wave.model.operation.wave.Transform;
import org.waveprotocol.wave.model.operation.wave.WaveletOperation;
import org.waveprotocol.wave.model.wave.ParticipantId;
import org.waveprotocol.wave.model.wave.data.impl.WaveletDataImpl;

import javax.annotation.Nullable;

import java.util.Collections;
import java.util.List;

/**
* @author danilatos@google.com (Daniel Danilatos)
*/
public class WaveObjectStoreModel implements SlobModel {

  // TODO(ohler): Replace these methods with getIndexEntry().
  public interface ReadableWaveletObject extends SlobModel.ReadableSlob {
    ParticipantId getCreator();
    long getLastModifiedMillis();
    List<ParticipantId> getParticipants();
  }

  private class WaveletObject implements ReadableWaveletObject, SlobModel.Slob {

    /**
     * Wavelet state. Created from first delta, then mutated in {@link #apply}.
     * Never cleared.
     */
    private WaveletDataImpl wavelet;

    private String cachedSnapshot = null;

    public WaveletObject(WaveletDataImpl initialState) {
      this.wavelet = initialState;
    }

    @Override @Nullable
    public String snapshot() {
      if (wavelet == null) {
        return null;
      }
      if (cachedSnapshot == null) {
        cachedSnapshot = serializer.serializeWavelet(wavelet);
      }
      return cachedSnapshot;
    }

    @Override
    public void apply(ChangeData<String> change) throws ChangeRejected {
      cachedSnapshot = null;
      WaveletOperation op;
      try {
        op = serializer.deserializeDelta(change.getPayload());
      } catch (MessageException e) {
        throw new ChangeRejected("Malformed op: " + change, e);
      }

      if (wavelet == null) {
        try {
          wavelet = WaveletUtil.buildWaveletFromInitialOps(
              IdHack.FAKE_WAVELET_NAME, Collections.singletonList(op));
        } catch (OperationException e) {
          throw new ChangeRejected("Invalid initial op: " + op, e);
        }
      } else {
        try {
          op.apply(wavelet);
        } catch (OperationException e) {
          // Operation failed. The wavelet is still intact, however, so just
          // report the failure and continue on.
          throw new ChangeRejected("Invalid op at version " + wavelet.getVersion() + ": " + op, e);
        }
      }
    }

    // TODO(ohler): Guarantee that the only method that will ever be called at
    // version 0 is apply().
    @Override public ParticipantId getCreator() {
      return wavelet.getCreator();
    }

    @Override public long getLastModifiedMillis() {
      return wavelet.getLastModifiedTime();
    }

    @Override public List<ParticipantId> getParticipants() {
      return ImmutableList.copyOf(wavelet.getParticipants());
    }
  }

  private final WaveSerializer serializer;

  @Inject
  public WaveObjectStoreModel(MessageSerializer messageSerializer) {
    this.serializer = new WaveSerializer(messageSerializer);
  }

  @Override
  public Slob create(String snapshot) throws InvalidSnapshot {
    try {
      return new WaveletObject(snapshot == null ? null
          : serializer.deserializeWavelet(IdHack.FAKE_WAVELET_NAME, snapshot));
    } catch (MessageException e) {
      throw new InvalidSnapshot(e);
    }
  }

  @Override
  public List<String> transform(
      List<ChangeData<String>> clientChanges, List<ChangeData<String>> serverChanges)
      throws ChangeRejected {
    try {
      WaveletOperation[] clientOps = deserializeOps(clientChanges);
      WaveletOperation[] serverOps = serverOps(serverChanges);

      for (WaveletOperation serverOp : serverOps) {
        for (int i = 0; i < clientOps.length; i++) {
          OperationPair<WaveletOperation> pair = Transform.transform(clientOps[i], serverOp);
          serverOp = pair.serverOp();
          clientOps[i] = pair.clientOp();
        }
      }

      List<String> ret = Lists.newArrayListWithCapacity(clientOps.length);
      for (int i = 0; i < clientOps.length; i++) {
        ret.add(serializer.serializeDelta(clientOps[i]));
      }

      return ret;
    } catch (TransformException e) {
      throw new ChangeRejected(e);
    } catch (MessageException e) {
      throw new ChangeRejected(e);
    }
  }

  // Server ops aren't expected to fail deserialization.
  private WaveletOperation[] serverOps(List<ChangeData<String>> serverChanges) {
    try {
      return deserializeOps(serverChanges);
    } catch (MessageException e) {
      throw new IllegalArgumentException("Malformed server op(s) " + serverChanges, e);
    }
  }

  private WaveletOperation[] deserializeOps(List<ChangeData<String>> changes)
      throws MessageException {
    WaveletOperation[] ops = new WaveletOperation[changes.size()];
    for (int i = 0; i < changes.size(); i++) {
      ChangeData<String> delta = changes.get(i);
      ops[i] = serializer.deserializeDelta(delta.getPayload());
    }
    return ops;
  }
}
TOP

Related Classes of com.google.walkaround.wave.server.model.WaveObjectStoreModel

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.