cc.kune.embed.client.panels.EmbedPresenter.java Source code

Java tutorial

Introduction

Here is the source code for cc.kune.embed.client.panels.EmbedPresenter.java

Source

/*
 *
 * Copyright (C) 2007-2015 Licensed to the Comunes Association (CA) under
 * one or more contributor license agreements (see COPYRIGHT for details).
 * The CA licenses this file to you under the GNU Affero General Public
 * License version 3, (the "License"); you may not use this file except in
 * compliance with the License. This file is part of kune.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package cc.kune.embed.client.panels;

import org.waveprotocol.box.webclient.client.atmosphere.AtmosphereConnectionImpl;
import org.waveprotocol.wave.util.escapers.GwtWaverefEncoder;

import cc.kune.common.client.log.Log;
import cc.kune.common.client.notify.NotifyUser;
import cc.kune.common.shared.i18n.I18n;
import cc.kune.common.shared.i18n.I18nTranslationService;
import cc.kune.common.shared.utils.UrlParam;
import cc.kune.core.client.events.UserSignOutEvent;
import cc.kune.core.client.events.UserSignOutEvent.UserSignOutHandler;
import cc.kune.core.client.services.ClientFileDownloadUtils;
import cc.kune.core.client.state.Session;
import cc.kune.core.client.state.TokenMatcher;
import cc.kune.core.client.state.impl.HistoryUtils;
import cc.kune.core.shared.JSONConstants;
import cc.kune.core.shared.dto.InitDataDTOJs;
import cc.kune.core.shared.dto.StateAbstractDTO;
import cc.kune.core.shared.dto.StateAbstractDTOJs;
import cc.kune.core.shared.dto.StateContentDTO;
import cc.kune.core.shared.dto.StateTokenJs;
import cc.kune.core.shared.dto.UserInfoDTOJs;
import cc.kune.embed.client.EmbedHelper;
import cc.kune.embed.client.conf.EmbedConfiguration;
import cc.kune.embed.client.events.EmbAppStartEvent;
import cc.kune.embed.client.events.EmbedOpenEvent;
import cc.kune.gspace.client.viewers.WaveViewer;
import cc.kune.wave.client.KuneWaveProfileManager;
import cc.kune.wave.client.kspecific.WaveClientManager;
import cc.kune.wave.client.kspecific.WaveClientProvider;

import com.google.gwt.core.client.Callback;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsonUtils;
import com.google.gwt.core.client.RunAsyncCallback;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.web.bindery.event.shared.EventBus;

/**
 * The Class EmbedPresenter is used to embed kune waves in other CMSs (for
 * instance)
 *
 * @author vjrj@ourproject.org (Vicente J. Ruiz Jurado)
 */
@Singleton
public class EmbedPresenter implements ValueChangeHandler<String> {

    /**
     * The Interface EmbedView.
     */
    public interface EmbedView extends WaveViewer {
    }

    private final ClientFileDownloadUtils clientDownUtils;
    private final boolean devMode = true;
    private final Session session;
    private final Provider<EmbedSitebar> sitebar;
    protected String stateTokenToOpen;
    private final Provider<EmbedView> view;

    /**
     * Instantiates a new embed presenter.
     *
     * @param eventBus
     *          the event bus
     * @param view
     *          the view
     * @param proxy
     *          the proxy
     * @param siteService
     *          the site service
     * @param service
     *          the service
     * @param waveClientManager
     *          the wave client manager
     * @param waveClient
     *          the wave client
     * @param matcher
     *          the matcher
     * @param session
     *          the session
     */

    @Inject
    public EmbedPresenter(final EventBus eventBus, final Provider<EmbedView> view,
            final WaveClientManager waveClientManager, final WaveClientProvider waveClient,
            final I18nTranslationService i18n, final Session session, final Provider<EmbedSitebar> sitebar,
            final ClientFileDownloadUtils clientDownUtils) {
        this.view = view;
        this.clientDownUtils = clientDownUtils;
        this.session = session;
        this.sitebar = sitebar;
        NotifyUser.showProgressLoading();
        Log.info("Starting embed presenter");
        // FIXME: Maybe use AppStart to detect browser compatibility in the future
        session.setEmbedded(true);
        TokenMatcher.init(GwtWaverefEncoder.INSTANCE);
        eventBus.addHandler(EmbedOpenEvent.getType(), new EmbedOpenEvent.EmbedOpenHandler() {
            @Override
            public void onEmbedOpen(final EmbedOpenEvent event) {
                stateTokenToOpen = event.getStateToken();
                Log.info("Received EmbedOpenEvent with token: " + stateTokenToOpen);
                if (session.getInitData() == null) {
                    // Not initialized
                    Log.debug("Session data not ready");
                } else {
                    // ok, we can continue
                    Log.debug("Session data ready");
                    getContentFromHistoryHash(stateTokenToOpen);
                }
            }
        });
        eventBus.addHandler(EmbAppStartEvent.getType(), new EmbAppStartEvent.EmbAppStartHandler() {
            @Override
            public void onAppStart(final EmbAppStartEvent event) {
                // This event is generated after configuration via JSNI
                Log.debug("App start event after conf loaded");
                onAppStarted();
            }
        });
        if (EmbedConfiguration.isReady()) {
            // The event was fired already, so start!
            Log.debug("App start after conf already loaded");
            // We set the prefix for avatars url with the server url
            onAppStarted();
        } else if (isCurrentHistoryHashValid(getCurrentHistoryHash())) {
            // The event was fired already, so start!
            Log.debug("App start after valid hash");
            // We set the prefix for avatars url with the server url
            EmbedConfiguration.setDefValues();
            onAppStarted();
        }
    }

    private void getContentFromHistoryHash(final String stateTokenS) {
        Log.info("Opening statetoken: " + stateTokenS);
        final boolean isGroupToken = TokenMatcher.isGroupToken(stateTokenS);
        final boolean isWaveToken = TokenMatcher.isWaveToken(stateTokenS);
        final String suffix = isGroupToken ? "" : isWaveToken ? "ByWaveRef" : "";

        if (isGroupToken || isWaveToken) {
            // Ok is a token like group.tool.number
            final String getContentUrl = EmbedHelper.getServerWithPath() + "cors/ContentCORSService/getContent"
                    + suffix + "?" + new UrlParam(JSONConstants.TOKEN_PARAM, URL.encodeQueryString(stateTokenS));

            // FIXME Exception if is not public?

            EmbedHelper.processRequest(getContentUrl, new Callback<Response, Void>() {

                @Override
                public void onFailure(final Void reason) {
                    notFound();
                }

                @Override
                public void onSuccess(final Response response) {
                    // final StateToken currentToken = new StateToken(currentHash);
                    NotifyUser.hideProgress();
                    final StateAbstractDTOJs state = JsonUtils.safeEval(response.getText());
                    final StateTokenJs stateTokenJs = (StateTokenJs) state.getStateToken();

                    // getContent returns the default content if doesn't finds the content
                    if ((isGroupToken && stateTokenS.equals(stateTokenJs.getEncoded()))
                            || (isWaveToken && stateTokenS.equals(state.getWaveRef()))) {
                        onGetContentSuccessful(session, EmbedHelper.parse(state));
                    } else {
                        // getContent returns def content if content not found
                        notFound();
                    }
                }
            });

        } else {
            // Do something
            notFound();
        }
    }

    private String getCurrentHistoryHash() {
        return HistoryUtils.undoHashbang(History.getToken());
    }

    private WaveViewer getView() {
        return view.get();
    }

    private boolean isCurrentHistoryHashValid(final String currentHistoryHash) {
        return currentHistoryHash != null
                && (TokenMatcher.isGroupToken(currentHistoryHash) || TokenMatcher.isWaveToken(currentHistoryHash));
    }

    /**
     * Not found.
     */
    private void notFound() {
        NotifyUser.important(I18n.t("Content not found"));
        NotifyUser.hideProgress();
    }

    private void onAppStarted() {
        // We set the prefix for avatars url with the server url
        final String serverUrl = EmbedConfiguration.get().getServerUrl();
        clientDownUtils.setPrefix(serverUrl);
        final String serverNoSlash = serverUrl.replaceAll("/$", "");
        KuneWaveProfileManager.urlPrefix = serverNoSlash;
        AtmosphereConnectionImpl.urlPrefix = serverNoSlash;

        final String userHash = session.getUserHash();
        Log.info("Started embed presenter with user hash: " + userHash);

        final String initUrl = EmbedHelper.getServerWithPath() + "cors/SiteCORSService/getInitData";

        EmbedHelper.processRequest(initUrl, new Callback<Response, Void>() {
            @Override
            public void onFailure(final Void reason) {
                // Do nothing
                Log.info("Failed to get init data");
            }

            @Override
            public void onSuccess(final Response response) {
                final InitDataDTOJs initData = JsonUtils.safeEval(response.getText());
                session.setInitData(EmbedHelper.parse(initData));
                final UserInfoDTOJs userInfo = (UserInfoDTOJs) initData.getUserInfo();
                if (userInfo != null) {
                    session.setUserHash(userInfo.getUserHash());
                    session.setCurrentUserInfo(EmbedHelper.parse(userInfo), null);
                } else {
                    if (session.getUserHash() != null) {
                        // Probably the session expired
                        session.signOut();
                    }
                }
                final String currentHash = getCurrentHistoryHash();
                final boolean isValid = isCurrentHistoryHashValid(currentHash);
                if (stateTokenToOpen != null) {
                    // The open event already received, so open the content
                    Log.info("Opening token from JSNI open call");
                    getContentFromHistoryHash(stateTokenToOpen);
                } else if (isValid) {
                    // We start the embed from the url #hash
                    Log.info("Opening token from history token");
                    stateTokenToOpen = currentHash;
                    getContentFromHistoryHash(currentHash);
                } else {
                    // We embed the document via JSNI, so, we wait for the open event
                }
                // We configure sign-out
                session.onUserSignOut(false, new UserSignOutHandler() {
                    @Override
                    public void onUserSignOut(final UserSignOutEvent event) {
                        Log.info("On user sign out");
                        if (stateTokenToOpen != null) {
                            getContentFromHistoryHash(stateTokenToOpen);
                        }
                    }
                });
            }
        });
    }

    private void onGetContentSuccessful(final Session session, final StateAbstractDTO state) {
        getView().clear();
        final StateContentDTO stateContent = (StateContentDTO) state;

        final boolean isLogged = session.isLogged();
        final boolean isParticipant = stateContent.isParticipant();
        Log.info("Is logged: " + isLogged + " isParticipant: " + isParticipant);
        final Boolean readOnly = EmbedConfiguration.get().getReadOnly();
        Log.info("Is readonly: " + readOnly);
        final Boolean isReadOnly = readOnly == null ? false : readOnly;
        if (isLogged && isParticipant && !isReadOnly) {
            getView().setEditableContent(stateContent);
        } else {
            getView().setContent(stateContent);
        }

        // FIXME use GWTP here?
        GWT.runAsync(new RunAsyncCallback() {
            @Override
            public void onFailure(final Throwable reason) {
                // By now, do nothing
            }

            @Override
            public void onSuccess() {
                sitebar.get().init(stateTokenToOpen);
            }

        });
    }

    @Override
    public void onValueChange(final ValueChangeEvent<String> event) {
        // Only used in dev mode
        if (devMode) {
            getContentFromHistoryHash(getCurrentHistoryHash());
        }
    }

    public void show() {
        RootPanel.get("kune-embed-hook").add(getView());
    }
}