/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates.
*
* 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.kie.workbench.common.stunner.client.widgets.presenters.session.impl;
import java.util.Optional;
import java.util.function.Predicate;
import org.jboss.errai.common.client.ui.ElementWrapperWidget;
import org.kie.workbench.common.stunner.client.widgets.notification.CommandNotification;
import org.kie.workbench.common.stunner.client.widgets.notification.Notification;
import org.kie.workbench.common.stunner.client.widgets.notification.NotificationContext;
import org.kie.workbench.common.stunner.client.widgets.notification.NotificationsObserver;
import org.kie.workbench.common.stunner.client.widgets.notification.ValidationFailedNotification;
import org.kie.workbench.common.stunner.client.widgets.palette.PaletteWidget;
import org.kie.workbench.common.stunner.client.widgets.palette.PaletteWidgetFactory;
import org.kie.workbench.common.stunner.client.widgets.presenters.session.SessionPresenter;
import org.kie.workbench.common.stunner.client.widgets.presenters.session.SessionViewer;
import org.kie.workbench.common.stunner.client.widgets.toolbar.Toolbar;
import org.kie.workbench.common.stunner.client.widgets.toolbar.ToolbarFactory;
import org.kie.workbench.common.stunner.core.client.api.SessionManager;
import org.kie.workbench.common.stunner.core.client.canvas.AbstractCanvasHandler;
import org.kie.workbench.common.stunner.core.client.components.palette.model.definition.DefinitionSetPalette;
import org.kie.workbench.common.stunner.core.client.service.ClientRuntimeError;
import org.kie.workbench.common.stunner.core.client.session.impl.AbstractClientReadOnlySession;
import org.kie.workbench.common.stunner.core.diagram.Diagram;
public abstract class AbstractSessionPresenter<D extends Diagram, H extends AbstractCanvasHandler,
S extends AbstractClientReadOnlySession, E extends SessionViewer<S, H, D>>
implements SessionPresenter<S, H, D> {
private final SessionManager sessionManager;
private final Optional<ToolbarFactory<S>> toolbarFactory;
private final Optional<PaletteWidgetFactory<DefinitionSetPalette, ?>> paletteFactory;
private final SessionPresenter.View view;
private final NotificationsObserver notificationsObserver;
private D diagram;
private Toolbar<S> toolbar;
private PaletteWidget<DefinitionSetPalette> palette;
private boolean hasToolbar = false;
private boolean hasPalette = false;
private Optional<Predicate<Notification.Type>> typePredicate;
@SuppressWarnings("unchecked")
protected AbstractSessionPresenter(final SessionManager sessionManager,
final SessionPresenter.View view,
final Optional<? extends ToolbarFactory<S>> toolbarFactory,
final Optional<PaletteWidgetFactory<DefinitionSetPalette, ?>> paletteFactory,
final NotificationsObserver notificationsObserver) {
this.sessionManager = sessionManager;
this.toolbarFactory = (Optional<ToolbarFactory<S>>) toolbarFactory;
this.paletteFactory = paletteFactory;
this.notificationsObserver = notificationsObserver;
this.view = view;
this.hasToolbar = true;
this.hasPalette = true;
this.typePredicate = Optional.empty();
}
protected abstract E getDisplayer();
@Override
public void open(final D diagram,
final S session,
final SessionPresenterCallback<S, D> callback) {
this.diagram = diagram;
notificationsObserver.onCommandExecutionFailed(this::showCommandError);
notificationsObserver.onValidationSuccess(this::showNotificationMessage);
notificationsObserver.onValidationFailed(this::showValidationError);
open(session,
callback);
}
public void open(final S item,
final SessionPresenterCallback<S, D> callback) {
beforeOpen(item);
getDisplayer().open(item,
new SessionViewer.SessionViewerCallback<S, D>() {
@Override
public void afterCanvasInitialized() {
callback.afterCanvasInitialized();
sessionManager.open(getInstance());
callback.afterSessionOpened();
}
@Override
public void onSuccess() {
onSessionOpened(item);
callback.onSuccess();
}
@Override
public void onError(final ClientRuntimeError error) {
AbstractSessionPresenter.this.showError(error);
callback.onError(error);
}
});
}
public void open(final S item,
final int width,
final int height,
final SessionPresenterCallback<S, D> callback) {
beforeOpen(item);
getDisplayer().open(item,
width,
height,
new SessionViewer.SessionViewerCallback<S, D>() {
@Override
public void afterCanvasInitialized() {
callback.afterCanvasInitialized();
sessionManager.open(getInstance());
callback.afterSessionOpened();
}
@Override
public void onSuccess() {
onSessionOpened(item);
callback.onSuccess();
}
@Override
public void onError(final ClientRuntimeError error) {
AbstractSessionPresenter.this.showError(error);
callback.onError(error);
}
});
}
@Override
public SessionPresenter<S, H, D> withToolbar(final boolean hasToolbar) {
this.hasToolbar = hasToolbar;
return this;
}
@Override
public SessionPresenter<S, H, D> withPalette(final boolean hasPalette) {
this.hasPalette = hasPalette;
return this;
}
@Override
public SessionPresenter<S, H, D> displayNotifications(final Predicate<Notification.Type> typePredicate) {
this.typePredicate = Optional.of(typePredicate);
return this;
}
@Override
public SessionPresenter<S, H, D> hideNotifications() {
typePredicate = Optional.empty();
return this;
}
public void scale(final int width,
final int height) {
getDisplayer().scale(width,
height);
}
public void clear() {
if (null != getPalette()) {
getPalette().unbind();
}
if (null != getToolbar()) {
getToolbar().clear();
}
getDisplayer().clear();
diagram = null;
}
@Override
public void destroy() {
destroyToolbar();
destroyPalette();
sessionManager.destroy();
getDisplayer().destroy();
getView().destroy();
diagram = null;
}
public S getInstance() {
return getDisplayer().getInstance();
}
@Override
public Toolbar<S> getToolbar() {
return toolbar;
}
@Override
public PaletteWidget<DefinitionSetPalette> getPalette() {
return palette;
}
@Override
public View getView() {
return view;
}
public H getHandler() {
return getDisplayer().getHandler();
}
protected void beforeOpen(final S item) {
getView().showLoading(true);
}
protected void onSessionOpened(final S session) {
destroyToolbar();
destroyPalette();
if (hasToolbar) {
toolbar = buildToolbar(session);
getView().setToolbarWidget(toolbar.getView());
}
if (hasPalette) {
this.palette = buildPalette(session);
getView().setPaletteWidget(ElementWrapperWidget.getWidget(getPalette().getElement()));
}
getView().setCanvasWidget(getDisplayer().getView());
getView().showLoading(false);
}
private void showMessage(final String message) {
if (isDisplayNotifications()) {
getView().showMessage(message);
}
}
private void showWarning(final String error) {
if (isDisplayErrors()) {
getView().showWarning(error);
}
}
private void showError(final String message) {
if (isDisplayErrors()) {
getView().showError(message);
}
}
private void showError(final ClientRuntimeError error) {
if (isDisplayErrors()) {
getView().showLoading(false);
getView().showError(error.getMessage());
}
}
private Toolbar<S> buildToolbar(final S session) {
if (!toolbarFactory.isPresent()) {
throw new UnsupportedOperationException("This session presenter with type [" + this.getClass().getName() + "] does not supports the toolbar.");
}
return toolbarFactory.get().build(session);
}
private PaletteWidget<DefinitionSetPalette> buildPalette(final S session) {
if (!paletteFactory.isPresent()) {
throw new UnsupportedOperationException("This session presenter with type [" + this.getClass().getName() + "] does not supports the palette.");
}
final Diagram diagram = session.getCanvasHandler().getDiagram();
return paletteFactory.get().newPalette(diagram.getMetadata().getShapeSetId(),
session.getCanvasHandler());
}
private void destroyToolbar() {
if (null != getToolbar()) {
getToolbar().destroy();
toolbar = null;
}
}
private void destroyPalette() {
if (null != getPalette()) {
getPalette().unbind();
getPalette().destroy();
}
}
private void showNotificationMessage(final Notification notification) {
if (isThisContext(notification)) {
showMessage(notification.getMessage());
}
}
private void showCommandError(final CommandNotification notification) {
if (isThisContext(notification)) {
showError(notification.getMessage());
}
}
private void showValidationError(final ValidationFailedNotification notification) {
if (isThisContext(notification)) {
if (Notification.Type.ERROR.equals(notification.getType())) {
showError(notification.getMessage());
} else {
showWarning(notification.getMessage());
}
}
}
private boolean isThisContext(final Notification notification) {
try {
final NotificationContext context = (NotificationContext) notification.getContext();
return null != getDiagram() && getDiagram().getName().equals(context.getDiagramName());
} catch (final ClassCastException e) {
return false;
}
}
protected D getDiagram() {
return diagram;
}
protected SessionManager getSessionManager() {
return sessionManager;
}
private boolean isDisplayNotifications() {
return typePredicate
.orElse(t -> false)
.test(Notification.Type.INFO);
}
private boolean isDisplayErrors() {
return typePredicate
.orElse(t -> false)
.or(Notification.Type.WARNING::equals)
.test(Notification.Type.ERROR);
}
}