All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mvp4g.client.history.PlaceService Maven / Gradle / Ivy

There is a newer version: 1.6.0
Show newest version
/*
 * Copyright (c) 2009 - 2017 - Pierre-Laurent Coirer, Frank Hossfeld
 *
 * 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.mvp4g.client.history;

import java.util.HashMap;
import java.util.Map;

import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.mvp4g.client.Mvp4gEventPasser;
import com.mvp4g.client.Mvp4gModule;

/**
 * Place Service defines the connection between the application and the browser history.
*
* When an event needs to be stored in the history, the place method of PlaceService is * called. This method will transform the event to an history token the following way:
*
* myurl#eventName?params
*
* where params is the string returned by the handling method of the history converter for the * event.
* If params is null, then the URL will be:
*
* myurl#eventName
*
* In case an event of a child module is stored, its history name and history names of all its * ascendant except the Root Module will be stored in the token:
*
* myurl#childModule/subChildModule/eventName?params
*
* By default "?" is used to seperate the event name from the parameters. You can change it thanks * to @HistoryConfiguration.
*
* If the token generated is supposed to be crawlable, then a "!" will be added before the token. * * @author plcoirier */ public class PlaceService implements ValueChangeHandler { public static final String MODULE_SEPARATOR = "/"; public static final String CRAWLABLE = "!"; private HistoryProxy history = null; private Mvp4gModule module = null; @SuppressWarnings("rawtypes") private Map converters = new HashMap(); private boolean enabled = true; private NavigationConfirmationInterface navigationConfirmation; /** * Build a PlaceService. */ public PlaceService() { this(HistoryProxyProvider.INSTANCE.get()); } /** * Build a PlaceService and inject an HistoryProxy instance.
*
* This constructor is handy when you want to test PlaceService without using the * GWT History class.
* It shouldn't be called otherwise. * * @param history * history proxy to inject */ protected PlaceService(HistoryProxy history) { this.history = history; history.addValueChangeHandler(this); } /** * Called when the History token has changed.
*
* Decode the history token and call the convertFromToken method of the history converters * associated with this action stored in the token.
*
* If token is equal to empty string, ask the event bus to dispatch an initEvent. * * @param event * event containing the new history token */ public void onValueChange(final ValueChangeEvent event) { confirmEvent(new NavigationEventCommand(module.getEventBus()) { protected void execute() { convertToken(event.getValue()); } }); } /** * Convert the token to an event * * @param token * the token to convert */ protected void convertToken(String token) { boolean toContinue = false; if (token != null) { if (token.startsWith(CRAWLABLE)) { token = token.substring(1); } toContinue = (token.length() > 0); } if (toContinue) { String[] result = parseToken(token); if (!forwardToChildModuleIfNeeded(result[0], result[1])) { dispatchEvent(result[0], result[1], module); } } else { module.sendInitEvent(); } } /** * Parse the token and return a string array. The first element of this array contains the event * name whereas the second element contains the parameters associated to the event. * * @param token * token to parse * * @return array of string */ protected String[] parseToken(String token) { String[] result = new String[2]; int index = token.lastIndexOf(getParamSeparator()); result[0] = (index == -1) ? token : token.substring(0, index); result[1] = (index == -1) ? null : token.substring(index + 1); return result; } /** * Check if this event is a child's module event. If it's the case, forward the token to the * child module and return true. * * @param eventName * name of the event that was stored in the token * @param param * parameters stored in the token * * @return true if this child module's event. */ protected boolean forwardToChildModuleIfNeeded(final String eventName, final String param) { boolean forAChild = eventName.contains(MODULE_SEPARATOR); if (forAChild) { Mvp4gEventPasser passer = new Mvp4gEventPasser(true) { @Override public void pass(Mvp4gModule module) { if ((Boolean) eventObjects[0]) { dispatchEvent(eventName, param, module); } else { sendNotFoundEvent(module); } } }; module.dispatchHistoryEvent(eventName, passer); } return forAChild; } /** * Dispatch the event thanks to the history converter. * * @param historyName * name of the event stored in the token * @param param * parameters stored in the token * @param module * module to which belongs the event */ @SuppressWarnings("unchecked") protected void dispatchEvent(String historyName, String param, Mvp4gModule module) { if (historyName != null) { @SuppressWarnings("rawtypes") HistoryConverter converter = converters.get(historyName); if (converter == null) { sendNotFoundEvent(module); } else { String[] tab = historyName.split(MODULE_SEPARATOR); String finalEventName = tab[tab.length - 1]; converter.convertFromToken(finalEventName, param, module.getEventBus()); } } else { sendNotFoundEvent(module); } } /** * Convert an event and its associated parameters to a token.
* * @param eventName * name of the event to store * @param param * string representation of the objects associated with the event that needs to be * stored in the token * @param onlyToken * if true, only the token will be generated and browser history won't change * * @return the generated token */ public String place(String eventName, String param, boolean onlyToken) { if (!enabled && !onlyToken) { return null; } String token = tokenize(eventName, param); if (converters.get(eventName) .isCrawlable()) { token = CRAWLABLE + token; } if (!onlyToken) { history.newItem(token, false); } return token; } /** * Transform an event and its parameters to a token * * @param eventName * event's name * @param param * event's parameters * * @return token to store in the history */ public String tokenize(String eventName, String param) { String token = eventName; if ((param != null) && (param.length() > 0)) { token = token + getParamSeparator() + param; } return token; } /** * @return separator used to differenciate the event's name and its parameters */ protected String getParamSeparator() { return "?"; } /** * Clear the history token stored in the browse history url by adding a new empty token */ public void clearHistory() { history.newItem("", false); } /** * Add a converter for an event. * * @param historyName * name of the event to store in the token * @param converter * converter associated with this event */ @SuppressWarnings("rawtypes") public void addConverter(String historyName, HistoryConverter converter) { converters.put(historyName, converter); } /** * @param module * the module to set */ public void setModule(Mvp4gModule module) { this.module = module; } /** * @param navigationConfirmation * the navigationConfirmation to set */ public void setNavigationConfirmation(NavigationConfirmationInterface navigationConfirmation) { this.navigationConfirmation = navigationConfirmation; } /** * Calls not found event. By default it will called a root module * event, but you can override the method if you want to call some * specific event for child module * * @param module * the last module where event wasn't found. If you will have * a correct historyName at the begin of url, then this will be a * child module, else rootModule. */ protected void sendNotFoundEvent(Mvp4gModule module) { this.module.sendNotFoundEvent(); } /** * Ask for user's confirmation before firing an event * * @param event * event to confirm */ public void confirmEvent(NavigationEventCommand event) { if (navigationConfirmation == null) { //no need to remove the confirmation, there is none event.fireEvent(false); } else { navigationConfirmation.confirm(event); } } /** * @param enabled * the enabled to set */ public void setEnabled(boolean enabled) { this.enabled = enabled; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy