/**
* Copyright 2009 Google Inc.
*
* 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 org.waveprotocol.wave.examples.fedone.waveserver;
import com.google.inject.Inject;
import com.google.inject.internal.Nullable;
import com.google.protobuf.RpcCallback;
import com.google.protobuf.RpcController;
import org.waveprotocol.wave.examples.fedone.util.Log;
import org.waveprotocol.wave.examples.fedone.util.URLEncoderDecoderBasedPercentEncoderDecoder;
import org.waveprotocol.wave.examples.fedone.waveserver.ClientFrontend.OpenListener;
import org.waveprotocol.wave.examples.fedone.waveserver.WaveClientRpc.ProtocolOpenRequest;
import org.waveprotocol.wave.examples.fedone.waveserver.WaveClientRpc.ProtocolSubmitRequest;
import org.waveprotocol.wave.examples.fedone.waveserver.WaveClientRpc.ProtocolSubmitResponse;
import org.waveprotocol.wave.examples.fedone.waveserver.WaveClientRpc.ProtocolWaveClientRpc;
import org.waveprotocol.wave.examples.fedone.waveserver.WaveClientRpc.ProtocolWaveletUpdate;
import org.waveprotocol.wave.federation.FederationErrorProto.FederationError;
import org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion;
import org.waveprotocol.wave.federation.Proto.ProtocolWaveletDelta;
import org.waveprotocol.wave.model.id.IdURIEncoderDecoder;
import org.waveprotocol.wave.model.id.URIEncoderDecoder.EncodingException;
import org.waveprotocol.wave.model.id.WaveId;
import org.waveprotocol.wave.model.id.WaveletName;
import org.waveprotocol.wave.model.wave.ParticipantId;
import org.waveprotocol.wave.waveserver.SubmitResultListener;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* RPC interface implementation for the wave server. Adapts incoming and
* outgoing RPCs to the client frontend interface.
*
*
*/
public class WaveClientRpcImpl implements ProtocolWaveClientRpc.Interface {
private static final Log LOG = Log.get(WaveClientRpcImpl.class);
private final ClientFrontend frontend;
private final IdURIEncoderDecoder uriCodec = new IdURIEncoderDecoder(
new URLEncoderDecoderBasedPercentEncoderDecoder());
/**
* Constructor.
*
* @param frontend ClientFrontend that consumes the operations.
*/
@Inject
public WaveClientRpcImpl(ClientFrontend frontend) {
this.frontend = frontend;
}
@Override
public void open(final RpcController controller, ProtocolOpenRequest request,
final RpcCallback<ProtocolWaveletUpdate> done) {
ParticipantId id = new ParticipantId(request.getParticipantId());
WaveId waveId;
try {
waveId = WaveId.deserialise(request.getWaveId());
} catch (IllegalArgumentException e) {
LOG.warning(e.getMessage());
controller.setFailed(e.getMessage());
return;
}
Set<String> prefixes = new HashSet<String>(request.getWaveletIdPrefixCount());
for (int i = 0; i < request.getWaveletIdPrefixCount(); ++i) {
prefixes.add(request.getWaveletIdPrefix(0));
}
frontend.openRequest(id, waveId, prefixes, request.getMaximumWavelets(),
false, new OpenListener() {
@Override
public void onFailure(String errorMessage) {
LOG.warning("openRequest failure: " + errorMessage);
controller.setFailed(errorMessage);
}
@Override
public void onUpdate(WaveletName waveletName,
@Nullable WaveletSnapshotAndVersions snapshot,
List<ProtocolWaveletDelta> deltas, @Nullable ProtocolHashedVersion endVersion,
@Nullable ProtocolHashedVersion committedVersion) {
ProtocolWaveletUpdate.Builder builder = ProtocolWaveletUpdate.newBuilder();
try {
builder.setWaveletName(uriCodec.waveletNameToURI(waveletName));
builder.addAllAppliedDelta(deltas);
if (snapshot != null) {
builder.setSnapshot(snapshot.snapshot);
if (snapshot.currentVersion != null) {
builder.setResultingVersion(snapshot.currentVersion);
}
if (snapshot.committedVersion != null) {
builder.setCommitNotice(snapshot.committedVersion);
}
} else {
if (endVersion != null) {
builder.setResultingVersion(endVersion);
}
if (committedVersion != null) {
builder.setCommitNotice(committedVersion);
}
}
done.run(builder.build());
} catch (EncodingException e) {
LOG.warning(e.getMessage());
controller.setFailed(e.getMessage());
}
}
});
}
@Override
public void submit(RpcController controller, ProtocolSubmitRequest request,
final RpcCallback<ProtocolSubmitResponse> done) {
WaveletName waveletName;
String errorMessage = null;
try {
waveletName = uriCodec.uriToWaveletName(request.getWaveletName());
frontend.submitRequest(waveletName, request.getDelta(), new SubmitResultListener() {
@Override
public void onFailure(FederationError error) {
done.run(ProtocolSubmitResponse.newBuilder()
.setOperationsApplied(0).setErrorMessage(error.getErrorMessage()).build());
}
@Override
public void onSuccess(int operationsApplied,
ProtocolHashedVersion hashedVersionAfterApplication,
long applicationTimestamp) {
done.run(ProtocolSubmitResponse.newBuilder()
.setOperationsApplied(operationsApplied)
.setHashedVersionAfterApplication(hashedVersionAfterApplication).build());
// TODO(arb): applicationTimestamp??
}
});
} catch (EncodingException e) {
errorMessage = e.getMessage();
}
if (errorMessage != null) {
LOG.warning(errorMessage);
done.run(ProtocolSubmitResponse.newBuilder()
.setOperationsApplied(0).setErrorMessage(errorMessage).build());
}
}
}