/**
* Copyright (C) 2011 BonitaSoft S.A.
* BonitaSoft, 31 rue Gustave Eiffel - 38000 Grenoble
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2.0 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.bonitasoft.web.toolkit.client;
import java.util.Map;
import org.bonitasoft.web.toolkit.client.common.Tree;
import org.bonitasoft.web.toolkit.client.common.TreeIndexed;
import org.bonitasoft.web.toolkit.client.common.i18n.AbstractI18n;
import org.bonitasoft.web.toolkit.client.common.i18n.AbstractI18n.LOCALE;
import org.bonitasoft.web.toolkit.client.common.json.JSonItemReader;
import org.bonitasoft.web.toolkit.client.common.json.JSonUnserializerClient;
import org.bonitasoft.web.toolkit.client.common.session.SessionDefinition;
import org.bonitasoft.web.toolkit.client.common.url.UrlOption;
import org.bonitasoft.web.toolkit.client.common.url.UrlSerializer;
import org.bonitasoft.web.toolkit.client.common.url.UrlUnserializer;
import org.bonitasoft.web.toolkit.client.common.url.UrlUtil;
import org.bonitasoft.web.toolkit.client.data.api.APICaller;
import org.bonitasoft.web.toolkit.client.data.api.callback.APICallback;
import org.bonitasoft.web.toolkit.client.data.item.IItem;
import org.bonitasoft.web.toolkit.client.ui.action.Action;
import org.bonitasoft.web.toolkit.client.ui.utils.I18n;
import org.bonitasoft.web.toolkit.client.ui.utils.Loader;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
/**
* @author Anthony Birembaut, Julien Mege
*/
public class ClientApplicationURL {
// Function, using GWT Generator Implementation
// public abstract void createViewTokens();
public static enum Target {
POPUP, ROOT
}
protected static final String DEFAULT_LANG = "en";
/**
* The cookie name for the forms locale
*/
public static final String FORM_LOCALE_COOKIE_NAME = "BOS_Locale";
public static final String TOKEN_FORM_APP = "perform";
public static final String TOKEN_EDIT = "edit";
public static final String TOKEN_ADD = "add";
public static final String TOKEN_DELETE = "delete";
protected static final String ATTRIBUTE_TOKEN = UrlOption.PAGE;
protected static final String ATTRIBUTE_LANG = UrlOption.LANG;
protected static final String ATTRIBUTE_PROFILE = UrlOption.PROFILE;
protected static final String ATTRIBUTE_TENANT = "tenant";
private TreeIndexed<String> attributes = new TreeIndexed<String>();
private static ClientApplicationURL self = null;
/**
* Default Constructor.
*/
public ClientApplicationURL() {
super();
// Singleton
self = this;
}
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// URL PARSING
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
protected TreeIndexed<String> parseToken() {
//unserialize twice since Firefox does not decode anymore window.location.hash since version 41
final String decodedToken = UrlUtil.unescape(History.getToken());
return UrlUnserializer.unserializeTreeNodeIndexed(decodedToken);
}
protected void parseUrl() {
// If Token or profile disappeared, keep the previous one
final String token = _getPageToken();
final String profileId = _getProfileId();
attributes = parseToken();
// If Token or profile disappeared, keep the previous one
if (token != null && _getPageToken() == null) {
_setPageToken(token, false);
}
if (profileId != null && _getProfileId() == null) {
_setProfileId(profileId);
}
}
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SETTERS AND GETTERS
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
protected String _getPageToken() {
return attributes.getValue(ATTRIBUTE_TOKEN);
}
protected String _getLang() {
return attributes.getValue(ATTRIBUTE_LANG);
}
protected String _getProfileId() {
return attributes.getValue(ATTRIBUTE_PROFILE);
}
protected String _getTenantId() {
return Window.Location.getParameter(ATTRIBUTE_TENANT);
}
private void _setPageToken(final String pageToken, final boolean refresh) {
if (pageToken == null) {
attributes.removeNode(ATTRIBUTE_TOKEN);
} else {
attributes.addValue(ATTRIBUTE_TOKEN, pageToken);
}
if (refresh) {
_refreshUrl(true);
}
}
private void _setProfileId(final String profileId) {
if (profileId == null) {
attributes.removeNode(ATTRIBUTE_PROFILE);
} else {
attributes.addValue(ATTRIBUTE_PROFILE, profileId);
}
}
public static TreeIndexed<String> getPageAttributes() {
return self._getPageAttributes();
}
private TreeIndexed<String> _getPageAttributes() {
final TreeIndexed<String> result = attributes.copy();
result.removeNode(ATTRIBUTE_LANG);
result.removeNode(ATTRIBUTE_PROFILE);
result.removeNode(ATTRIBUTE_TOKEN);
return result;
}
private void _setPageAttributes(final TreeIndexed<String> attributes) {
final String token = _getPageToken();
final String profileId = _getProfileId();
this.attributes = attributes.copy();
if (token != null) {
_setPageToken(token, false);
}
if (profileId != null) {
_setProfileId(profileId);
}
}
private void _addAttribute(final String key, final String... value) {
self.attributes.addValue(key, value);
}
private void _removeAttribute(final String key) {
self.attributes.removeNode(key);
}
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SETTERS AND GETTERS (static)
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static String getPageToken() {
return self._getPageToken();
}
public static String getLang() {
return self._getLang();
}
public static String getProfileId() {
return self._getProfileId();
}
public static String getTenantId() {
return self._getTenantId();
}
public static void setPageToken(final String pageToken, final boolean refresh) {
self._setPageToken(pageToken, refresh);
}
public static void setPageAttributes(final TreeIndexed<String> params) {
self._setPageAttributes(params);
}
public static void setLang(final LOCALE lang) {
setLang(lang, true);
}
private static void setLang(final LOCALE lang, final boolean refresh) {
Session.addParameter(ATTRIBUTE_LANG, lang.toString());
ParametersStorageWithCookie.addParameter(ATTRIBUTE_LANG, lang.toString());
Cookies.setCookie(FORM_LOCALE_COOKIE_NAME, lang.toString());
AbstractI18n.setDefaultLocale(lang);
if (refresh) {
Window.Location.reload();
}
}
public static void setProfileId(final String profileId) {
self._setProfileId(profileId);
}
private void _refreshUrl(final boolean refreshView) {
if (parseToken().equals(attributes)) {
// Same URL attributes, do nothing
return;
}
History.newItem("?" + UrlSerializer.serialize(attributes), false);
if (refreshView) {
refreshView();
}
}
private void _refresh() {
refreshView();
}
public static void refreshUrl(final boolean refreshView) {
self._refreshUrl(refreshView);
}
public static void refresh() {
self._refresh();
}
public static void addAttribute(final String key, final String... value) {
self._addAttribute(key, value);
}
public static void removeAttribute(final String key) {
self._removeAttribute(key);
}
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// INIT AND REFRESH
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
protected void initSession(final Action callback) {
new APICaller(new SessionDefinition()).get("unusedId", new APICallback() {
@Override
public void onSuccess(final int httpStatusCode, final String response, final Map<String, String> headers) {
if (headers.get("X-Bonita-API-Token") != null) {
UserSessionVariables.addUserVariable(UserSessionVariables.API_TOKEN, headers.get("X-Bonita-API-Token"));
}
final IItem session = JSonItemReader.parseItem(response, new SessionDefinition());
for (final String name : session.getAttributeNames()) {
if (name.equals("conf")) {
AvailableTokens.tokens.addAll(((Tree<String>) JSonUnserializerClient.unserializeTree(session.getAttributeValue(name))).getValues());
// Session.addParameter(name, ((Tree<String>) JSonUnserializerClient.unserializeTree(session.getAttributeValue(name))).getValues());
} else {
Session.addParameter(name, session.getAttributeValue(name));
}
}
// TODO Add here assertions on parameters mandatory for the toolkit
// Example : assert Session.getUserId() != null;
callback.execute();
}
});
}
protected void initLang(final Action callback) {
// Check if the lang is in the URL
String newLang = parseToken().getValue(ATTRIBUTE_LANG);
// Clean
if (newLang != null) {
// TODO remove lang from URL and replace last history URL
} else {
// Check if the lang is in the session
newLang = Session.getParameter(FORM_LOCALE_COOKIE_NAME);
if (newLang == null) {
// Check if the lang is in the cookie
newLang = ParametersStorageWithCookie.getParameter(FORM_LOCALE_COOKIE_NAME);
if (newLang == null) {
// else we set the default lang
newLang = DEFAULT_LANG;
}
}
}
// Save the currentLang
if (!newLang.toString().equals(Session.getParameter(ATTRIBUTE_LANG))) {
Session.addParameter(ATTRIBUTE_LANG, newLang.toString());
ParametersStorageWithCookie.addParameter(ATTRIBUTE_LANG, newLang.toString());
}
// Load i18n data
final LOCALE currentLocale = AbstractI18n.stringToLocale(Session.getParameter(ATTRIBUTE_LANG));
AbstractI18n.setDefaultLocale(currentLocale);
I18n.getInstance().loadLocale(currentLocale, callback);
}
// First display of a view
protected void initView() {
// Hide global loader
Loader.hideLoader();
if (_getPageToken() != null && _getProfileId() != null) {
ViewController.showView(_getPageToken(), _getPageAttributes());
}
}
protected void refreshView() {
if (History.getToken().contains("_p=")) {
parseUrl();
ViewController.showView(_getPageToken(), _getPageAttributes());
}
}
}