/*
* Copyright 2015 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.uberfire.client.mvp;
import java.util.Set;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import org.uberfire.client.workbench.PanelManager;
import org.uberfire.client.workbench.WorkbenchServicesProxy;
import org.uberfire.client.workbench.events.PerspectiveChange;
import org.uberfire.mvp.Command;
import org.uberfire.mvp.ParameterizedCommand;
import org.uberfire.mvp.PlaceRequest;
import org.uberfire.workbench.model.PanelDefinition;
import org.uberfire.workbench.model.PartDefinition;
import org.uberfire.workbench.model.PerspectiveDefinition;
import static org.uberfire.commons.validation.PortablePreconditions.checkNotNull;
import static org.uberfire.plugin.PluginUtil.ensureIterable;
@ApplicationScoped
public class PerspectiveManagerImpl implements PerspectiveManager {
@Inject
private PanelManager panelManager;
@Inject
private WorkbenchServicesProxy wbServices;
@Inject
private Event<PerspectiveChange> perspectiveChangeEvent;
@Inject
private ActivityBeansCache activityBeansCache;
private PerspectiveActivity currentPerspective;
private PerspectiveDefinition livePerspectiveDef;
@Override
public void switchToPerspective(final PlaceRequest placeRequest,
final PerspectiveActivity activity,
final ParameterizedCommand<PerspectiveDefinition> doWhenFinished) {
// switching perspectives is a chain of async operations. they're declared here
// in reverse order (last to first):
NotifyOthersOfPerspectiveChangeCommand fourthOperation = new NotifyOthersOfPerspectiveChangeCommand(placeRequest,
doWhenFinished);
BuildPerspectiveFromDefinitionCommand thirdOperation = new BuildPerspectiveFromDefinitionCommand(activity,
fourthOperation);
FetchPerspectiveCommand secondOperation = new FetchPerspectiveCommand(activity,
thirdOperation);
secondOperation.execute();
}
@Override
public PerspectiveActivity getCurrentPerspective() {
return currentPerspective;
}
@Override
public PerspectiveDefinition getLivePerspectiveDefinition() {
return livePerspectiveDef;
}
@Override
public void savePerspectiveState(Command doWhenFinished) {
if (currentPerspective != null && !currentPerspective.isTransient()) {
wbServices.save(currentPerspective.getIdentifier(),
livePerspectiveDef,
doWhenFinished);
} else {
doWhenFinished.execute();
}
}
@Override
public void loadPerspectiveStates(final ParameterizedCommand<Set<PerspectiveDefinition>> doWhenFinished) {
wbServices.loadPerspectives(doWhenFinished);
}
@Override
public void removePerspectiveState(final String perspectiveId,
final Command doWhenFinished) {
wbServices.removePerspectiveState(perspectiveId,
doWhenFinished);
}
@Override
public void removePerspectiveStates(final Command doWhenFinished) {
wbServices.removePerspectiveStates(doWhenFinished);
}
/**
* Fetches the given perspective's definition either from the server (if non-transient) or from the activity itself
* (if transient or if the fetch call fails).
*/
class FetchPerspectiveCommand implements Command {
private final PerspectiveActivity perspective;
private final ParameterizedCommand<PerspectiveDefinition> doAfterFetch;
public FetchPerspectiveCommand(PerspectiveActivity perspective,
ParameterizedCommand<PerspectiveDefinition> doAfterFetch) {
this.perspective = checkNotNull("perspective",
perspective);
this.doAfterFetch = checkNotNull("doAfterFetch",
doAfterFetch);
}
@Override
public void execute() {
currentPerspective = perspective;
if (perspective.isTransient()) {
//Transient Perspectives are not saved and hence cannot be loaded
doAfterFetch.execute(perspective.getDefaultPerspectiveLayout());
} else {
wbServices.loadPerspective(perspective.getIdentifier(),
new ParameterizedCommand<PerspectiveDefinition>() {
@Override
public void execute(final PerspectiveDefinition response) {
if (isAValidDefinition(response)) {
doAfterFetch.execute(response);
} else {
doAfterFetch.execute(perspective.getDefaultPerspectiveLayout());
}
}
});
}
}
boolean isAValidDefinition(PerspectiveDefinition response) {
return response != null && allThePartsAreValid(response.getRoot());
}
private boolean allThePartsAreValid(PanelDefinition panel) {
if (!checkIfAllPlacesAreValidActivities(panel)) {
return false;
} else {
for (PanelDefinition child : ensureIterable(panel.getChildren())) {
if (!allThePartsAreValid(child)) {
return false;
}
}
}
return true;
}
private boolean checkIfAllPlacesAreValidActivities(PanelDefinition child) {
for (PartDefinition partDefinition : ensureIterable(child.getParts())) {
PlaceRequest place = partDefinition.getPlace();
if (!activityBeansCache.hasActivity(place.getIdentifier())) {
return false;
}
}
return true;
}
}
/**
* Builds up the panels of a perspective based on the structure described in a given {@link PerspectiveDefinition}.
*/
class BuildPerspectiveFromDefinitionCommand implements ParameterizedCommand<PerspectiveDefinition> {
private final ParameterizedCommand<PerspectiveDefinition> doWhenFinished;
private final PerspectiveActivity activity;
public BuildPerspectiveFromDefinitionCommand(PerspectiveActivity activity,
ParameterizedCommand<PerspectiveDefinition> doWhenFinished) {
this.activity = checkNotNull("activity",
activity);
this.doWhenFinished = checkNotNull("doWhenFinished",
doWhenFinished);
}
@Override
public void execute(PerspectiveDefinition perspectiveDef) {
if (livePerspectiveDef != null) {
tearDownChildPanelsRecursively(livePerspectiveDef.getRoot());
}
livePerspectiveDef = perspectiveDef;
panelManager.setRoot(activity,
perspectiveDef.getRoot());
setupPanelRecursively(perspectiveDef.getRoot());
doWhenFinished.execute(perspectiveDef);
}
private void tearDownChildPanelsRecursively(final PanelDefinition panel) {
for (PanelDefinition child : ensureIterable(panel.getChildren())) {
tearDownChildPanelsRecursively(child);
panelManager.removeWorkbenchPanel(child);
}
}
private void setupPanelRecursively(final PanelDefinition panel) {
for (PanelDefinition child : ensureIterable(panel.getChildren())) {
final PanelDefinition target = panelManager.addWorkbenchPanel(panel,
child,
child.getPosition());
setupPanelRecursively(target);
}
}
}
class NotifyOthersOfPerspectiveChangeCommand implements ParameterizedCommand<PerspectiveDefinition> {
private final PlaceRequest placeRequest;
private final ParameterizedCommand<PerspectiveDefinition> doWhenFinished;
public NotifyOthersOfPerspectiveChangeCommand(final PlaceRequest placeRequest,
final ParameterizedCommand<PerspectiveDefinition> doWhenFinished) {
this.placeRequest = checkNotNull("placeRequest",
placeRequest);
this.doWhenFinished = checkNotNull("doWhenFinished",
doWhenFinished);
}
@Override
public void execute(PerspectiveDefinition perspectiveDef) {
perspectiveChangeEvent.fire(new PerspectiveChange(placeRequest,
perspectiveDef,
currentPerspective.getMenus(),
currentPerspective.getIdentifier()));
doWhenFinished.execute(perspectiveDef);
}
}
}