// Copyright 2012 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.collide.clientlibs.invalidation; import com.google.collide.dto.client.DtoUtils; import com.google.collide.dtogen.shared.ServerToClientDto; import com.google.collide.shared.invalidations.InvalidationObjectId; import com.google.collide.shared.util.ListenerRegistrar.Remover; import javax.annotation.Nullable; /** * An object which can register and unregister for Tango invalidations. */ public interface InvalidationRegistrar { /** * A handle to the registration for invalidations. * * <p> * Clients that registered with {@code recoverMissingPayloads=true} must call * {@link #initializeRecoverer(long)} after receiving the initial object * contents. * */ public interface RemovableHandle extends Remover { /** * Sets the next expected version of the object. * * <p> * This is required to bootstrap the ability to recover missing payloads or * squelched invalidations. * * <p> * This can be called multiple times to tell the tango recoverer that your * model is now at a new version. */ void initializeRecoverer(long nextExpectedVersion); } /** * A listener for Tango object invalidation. */ public interface Listener { /** * A handle to notify the caller of {@link Listener#onInvalidated} that * this invalidation will be processed asychronously. This means the caller will not call again * until the current invalidation has finished being processed. */ public interface AsyncProcessingHandle { /** * Notifies the caller that the invalidation will be processed asychronously. * * <p> * {@link #finishedAsyncProcessing()} must be called when the invalidation has been processed. */ void startedAsyncProcessing(); /** * Notifies the caller of {@link Listener#onInvalidated} that the * invalidation has finished being processed. */ void finishedAsyncProcessing(); } /** * @param payload the invalidation payload, or null if no payload arrived * @param asyncProcessingHandle for objects that require payload recovery, this will tell the * recovery stack to allow for async processing of this payload */ void onInvalidated(String objectName, long version, @Nullable String payload, AsyncProcessingHandle asyncProcessingHandle); } /** * A listener which handles deserializing a Tango payload into a given DTO * type. * * @param <T> the type of dto. */ public abstract static class DtoListener<T extends ServerToClientDto> implements Listener { private final int routingType; public DtoListener(int routingType) { this.routingType = routingType; } @Override public void onInvalidated(String objectName, long version, String payload, AsyncProcessingHandle asyncProcessingHandle) { T dto = null; if (payload != null) { dto = DtoUtils.parseAsDto(payload, routingType); } onInvalidatedDto(objectName, version, dto, asyncProcessingHandle); } /** * @see Listener#onInvalidated */ public abstract void onInvalidatedDto(String objectName, long version, T dto, AsyncProcessingHandle asyncProcessingHandle); } /** * Registers the client to receive invalidations for the given object. * * <p> * If the client requires recovering from missing payloads ({@code * recoverMissingPayloads} is true), the suggested usage pattern is: * <ul> * <li>Register for Tango invalidations using this method</li> * <li>Out-of-band (e.g. via XHR) fetch the initial contents of the object * </li> * <li>Call {@link RemovableHandle#initializeRecoverer} with the fetched * object's version</li> * </ul> */ public RemovableHandle register(InvalidationObjectId<?> objectId, Listener eventListener); public void unregister(InvalidationObjectId<?> objectId); }