/** * 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.model.supplement; import org.waveprotocol.wave.model.supplement.ObservablePrimitiveSupplement.Listener; import org.waveprotocol.wave.model.adt.ObservableBasicMap; import org.waveprotocol.wave.model.adt.docbased.DocumentBasedBasicMap; import org.waveprotocol.wave.model.document.util.DocumentEventRouter; import org.waveprotocol.wave.model.util.CollectionUtils; import org.waveprotocol.wave.model.util.Preconditions; import org.waveprotocol.wave.model.util.ReadableStringMap; import org.waveprotocol.wave.model.util.Serializer; import org.waveprotocol.wave.model.util.StringMap; /** * Implements the gadget state, using the {@link DocumentBasedBasicMap} * embedding. * * @param <E> Element type of the document implementation. */ public class DocumentBasedGadgetState<E> implements GadgetState { private final ObservableBasicMap<String, String> state; private final DocumentEventRouter<? super E, E, ?> router; private final E container; DocumentBasedGadgetState(DocumentEventRouter<? super E, E, ?> router, E container) { this.router = router; this.container = container; state = DocumentBasedBasicMap.create(router, container, Serializer.STRING, Serializer.STRING, WaveletBasedSupplement.STATE_TAG, WaveletBasedSupplement.NAME_ATTR, WaveletBasedSupplement.VALUE_ATTR); } /** * Creates document-based gadget state object. * * @param router Router for the document that holds the state. * @param container Element in which the state is kept. * @param id ID of the gadget that uses the state. * @param listener Listener for gadget state changes. * @return A new gadget state tracker. */ public static <E> DocumentBasedGadgetState<E> create( DocumentEventRouter<? super E, E, ?> router, E container, String id, Listener listener) { DocumentBasedGadgetState<E> state = new DocumentBasedGadgetState<E>(router, container); state.installListeners(id, listener); return state; } /** * Injects listeners into the underlying ADTs that translate their events * into primitive-supplement events. * * @param gadgetId ID of the gadget. * @param listener Listener to notify. */ private void installListeners(final String gadgetId, final Listener listener) { state.addListener(new ObservableBasicMap.Listener<String, String>() { @Override public void onEntrySet(String key, String oldValue, String newValue) { listener.onGadgetStateChanged(gadgetId, key, oldValue, newValue); } }); } @Override public ReadableStringMap<String> getStateMap() { if (state.keySet().isEmpty()) { return CollectionUtils.<String> emptyMap(); } StringMap<String> stateMap = CollectionUtils.createStringMap(); for (String key : state.keySet()) { stateMap.put(key, state.get(key)); } return stateMap; } @Override public void remove() { router.getDocument().deleteNode(container); } @Override public void setState(String key, String value) { Preconditions.checkNotNull(key, "Private gadget state key is null."); if (value != null) { state.put(key, value); } else { state.remove(key); } } }