/** * Copyright 2010 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.client.concurrencycontrol; import org.waveprotocol.wave.model.operation.Operation; import org.waveprotocol.wave.model.operation.OperationException; import org.waveprotocol.wave.model.operation.OperationRuntimeException; import org.waveprotocol.wave.model.operation.SilentOperationSink; /** * Connects a data object with operation sinks that make it live. * * @param <T> type to which operations apply * @param <O> operation type */ public final class LiveTarget<T, O extends Operation<? super T>> { /** Target data object. */ private final T target; /** Sink that executes consumed operations. */ private final SilentOperationSink<O> executor; /** Output sink for outgoing operations. */ private final ProxyOperationSink<O> output; /** * Creates a live-target triple. */ private LiveTarget(T target, SilentOperationSink<O> executor, ProxyOperationSink<O> output) { this.target = target; this.executor = executor; this.output = output; } /** * Creates a live-target. */ public static <T, O extends Operation<? super T>> LiveTarget<T, O> create(final T data) { ProxyOperationSink<O> output = ProxyOperationSink.create(); SilentOperationSink<O> executor = new SilentOperationSink<O>() { @Override public void consume(O operation) { try { operation.apply(data); } catch (OperationException e) { // Fail this object permanently throw new OperationRuntimeException("Error applying op", e); } } }; return new LiveTarget<T, O>(data, executor, output); } /** @return the target object being controlled by operations. */ public T getTarget() { return target; } /** @return the sink that executes operations on the target. */ public SilentOperationSink<O> getExecutorSink() { return executor; } /** @return the sink to which operations from the target are sent. */ public ProxyOperationSink<O> getOutputSink() { return output; } }