// 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.client.history; import com.google.collide.client.util.logging.Log; import com.google.collide.clientlibs.navigation.NavigationToken; import com.google.collide.json.client.JsoStringMap; import com.google.collide.json.shared.JsonArray; import com.google.collide.json.shared.JsonStringMap; /** * The Root {@link Place}. We are in the Root place implicitly via onModuleLoad. * Thus the RootPlace has no associated {@link PlaceNavigationHandler} or * {@link PlaceNavigationEvent}. */ public class RootPlace extends Place { class NullEvent extends PlaceNavigationEvent<RootPlace> { protected NullEvent() { super(RootPlace.this); } @Override public JsonStringMap<String> getBookmarkableState() { Log.error(getClass(), "The ROOT place should never need bookmarkable state!"); return null; } } /** * The Root Place is implicit. We get here from onModuleLoad. */ static class NullHandler extends PlaceNavigationHandler<NullEvent> { @Override protected void enterPlace(NullEvent navigationEvent) { Log.error(getClass(), "The Navigation handler for the ROOT Place should never fire!"); } } public static final RootPlace PLACE = new RootPlace(); public static final String ROOT_NAME = "Root"; /** * This is an optional default for navigations on the Root that fail. note * that this place MUST be able to handle a navigation with an empty key/value * state map. */ private Place defaultPlace; private RootPlace() { super(ROOT_NAME); // The Root is always active. setIsActive(true, null); } @Override public NullEvent createNavigationEvent(JsonStringMap<String> decodedState) { Log.error(getClass(), "The ROOT Place should never need to create a Navigation Event!"); return null; } @Override public void dispatchHistory(JsonArray<NavigationToken> historyPieces) { if (historyPieces.isEmpty() || (getRegisteredChild(historyPieces.get(0).getPlaceName()) == null)) { // If the history string is empty, or if the first navigation is bogus, // then we go to the default child Place if any. if (defaultPlace != null) { fireChildPlaceNavigation(defaultPlace.createNavigationEvent(JsoStringMap.<String>create())); } return; } super.dispatchHistory(historyPieces); } /** * Same as {@link Place#registerChildHandler(Place, PlaceNavigationHandler)}, except this takes an * additional parameter to specify whether or not we should treat this child {@link Place} as a * default fallback for bogus navigations. */ public <E extends PlaceNavigationEvent<C>, N extends PlaceNavigationHandler<E>, C extends Place> void registerChildHandler(C childPlace, N handler, boolean isDefault) { if (isDefault) { this.defaultPlace = childPlace; } super.registerChildHandler(childPlace, handler); } }