/* * Copyright 2016 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.screens.library.client.util; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Event; import javax.enterprise.event.Observes; import javax.inject.Inject; import org.ext.uberfire.social.activities.model.ExtendedTypes; import org.ext.uberfire.social.activities.model.SocialFileSelectedEvent; import org.guvnor.asset.management.social.AssetManagementEventTypes; import org.guvnor.common.services.project.context.ProjectContext; import org.guvnor.common.services.project.context.ProjectContextChangeEvent; import org.guvnor.common.services.project.events.DeleteProjectEvent; import org.guvnor.common.services.project.events.RenameProjectEvent; import org.guvnor.common.services.project.model.Project; import org.guvnor.common.services.project.social.ProjectEventType; import org.guvnor.structure.organizationalunit.OrganizationalUnit; import org.guvnor.structure.repositories.Repository; import org.jboss.errai.common.client.api.Caller; import org.jboss.errai.common.client.api.RemoteCallback; import org.jboss.errai.ioc.client.api.ManagedInstance; import org.jboss.errai.ui.client.local.spi.TranslationService; import org.kie.workbench.common.screens.examples.client.wizard.ExamplesWizard; import org.kie.workbench.common.screens.explorer.model.URIStructureExplorerModel; import org.kie.workbench.common.screens.explorer.service.ExplorerService; import org.kie.workbench.common.screens.library.api.LibraryService; import org.kie.workbench.common.screens.library.api.ProjectInfo; import org.kie.workbench.common.screens.library.client.events.AssetDetailEvent; import org.kie.workbench.common.screens.library.client.events.ProjectDetailEvent; import org.kie.workbench.common.screens.library.client.perspective.LibraryPerspective; import org.kie.workbench.common.screens.library.client.resources.i18n.LibraryConstants; import org.kie.workbench.common.screens.library.client.widgets.LibraryToolbarPresenter; import org.kie.workbench.common.widgets.client.handlers.NewResourceSuccessEvent; import org.kie.workbench.common.workbench.client.docks.AuthoringWorkbenchDocks; import org.uberfire.backend.vfs.ObservablePath; import org.uberfire.backend.vfs.Path; import org.uberfire.backend.vfs.VFSService; import org.uberfire.client.mvp.PlaceManager; import org.uberfire.client.mvp.PlaceStatus; import org.uberfire.client.workbench.events.PlaceGainFocusEvent; import org.uberfire.ext.editor.commons.client.event.ConcurrentRenameAcceptedEvent; import org.uberfire.ext.widgets.common.client.breadcrumbs.UberfireBreadcrumbs; import org.uberfire.mvp.Command; import org.uberfire.mvp.PlaceRequest; import org.uberfire.mvp.impl.ConditionalPlaceRequest; import org.uberfire.mvp.impl.DefaultPlaceRequest; import org.uberfire.mvp.impl.PathPlaceRequest; import org.uberfire.workbench.events.NotificationEvent; import org.uberfire.workbench.model.impl.PartDefinitionImpl; @ApplicationScoped public class LibraryPlaces { public static final String LIBRARY_PERSPECTIVE = "LibraryPerspective"; public static final String NEW_PROJECT_SCREEN = "NewProjectScreen"; public static final String EMPTY_LIBRARY_SCREEN = "EmptyLibraryScreen"; public static final String LIBRARY_SCREEN = "LibraryScreen"; public static final String EMPTY_PROJECT_SCREEN = "EmptyProjectScreen"; public static final String PROJECT_SCREEN = "ProjectScreen"; public static final String PROJECT_DETAIL_SCREEN = "ProjectsDetailScreen"; public static final String ORGANIZATIONAL_UNITS_SCREEN = "LibraryOrganizationalUnitsScreen"; public static final String PROJECT_SETTINGS = "projectScreen"; public static final String PROJECT_EXPLORER = "org.kie.guvnor.explorer"; public static final String MESSAGES = "org.kie.workbench.common.screens.messageconsole.MessageConsole"; public static final String REPOSITORY_STRUCTURE_SCREEN = "repositoryStructureScreen"; public static final List<String> LIBRARY_PLACES = Collections.unmodifiableList(new ArrayList<String>(7) {{ add(NEW_PROJECT_SCREEN); add(EMPTY_LIBRARY_SCREEN); add(LIBRARY_SCREEN); add(EMPTY_PROJECT_SCREEN); add(PROJECT_SCREEN); add(PROJECT_DETAIL_SCREEN); add(ORGANIZATIONAL_UNITS_SCREEN); add(PROJECT_SETTINGS); add(MESSAGES); }}); private UberfireBreadcrumbs breadcrumbs; private TranslationService ts; private Event<ProjectDetailEvent> projectDetailEvent; private Event<AssetDetailEvent> assetDetailEvent; private ResourceUtils resourceUtils; private Caller<LibraryService> libraryService; private PlaceManager placeManager; private LibraryPerspective libraryPerspective; private ProjectContext projectContext; private LibraryToolbarPresenter libraryToolbar; private AuthoringWorkbenchDocks docks; private Event<ProjectContextChangeEvent> projectContextChangeEvent; private ExamplesUtils examplesUtils; private Event<NotificationEvent> notificationEvent; private ManagedInstance<ExamplesWizard> examplesWizards; private TranslationUtils translationUtils; private Caller<VFSService> vfsService; private Caller<ExplorerService> explorerService; private boolean docksReady = false; private boolean docksHidden = true; private Project lastViewedProject = null; private boolean closingLibraryPlaces = false; @Inject public LibraryPlaces(final UberfireBreadcrumbs breadcrumbs, final TranslationService ts, final Event<ProjectDetailEvent> projectDetailEvent, final Event<AssetDetailEvent> assetDetailEvent, final ResourceUtils resourceUtils, final Caller<LibraryService> libraryService, final PlaceManager placeManager, final LibraryPerspective libraryPerspective, final ProjectContext projectContext, final LibraryToolbarPresenter libraryToolbar, final AuthoringWorkbenchDocks docks, final Event<ProjectContextChangeEvent> projectContextChangeEvent, final ExamplesUtils examplesUtils, final Event<NotificationEvent> notificationEvent, final ManagedInstance<ExamplesWizard> examplesWizards, final TranslationUtils translationUtils, final Caller<VFSService> vfsService, final Caller<ExplorerService> explorerService) { this.breadcrumbs = breadcrumbs; this.ts = ts; this.projectDetailEvent = projectDetailEvent; this.assetDetailEvent = assetDetailEvent; this.resourceUtils = resourceUtils; this.libraryService = libraryService; this.placeManager = placeManager; this.libraryPerspective = libraryPerspective; this.projectContext = projectContext; this.libraryToolbar = libraryToolbar; this.docks = docks; this.projectContextChangeEvent = projectContextChangeEvent; this.examplesUtils = examplesUtils; this.notificationEvent = notificationEvent; this.examplesWizards = examplesWizards; this.translationUtils = translationUtils; this.vfsService = vfsService; this.explorerService = explorerService; } public ProjectInfo getProjectInfo() { return new ProjectInfo(projectContext.getActiveOrganizationalUnit(), projectContext.getActiveRepository(), projectContext.getActiveBranch(), projectContext.getActiveProject()); } public void onSelectPlaceEvent(@Observes final PlaceGainFocusEvent placeGainFocusEvent) { if (isLibraryPerspectiveOpen() && !closingLibraryPlaces) { final ProjectInfo projectInfo = getProjectInfo(); final PlaceRequest place = placeGainFocusEvent.getPlace(); if (place instanceof PathPlaceRequest) { final PathPlaceRequest pathPlaceRequest = (PathPlaceRequest) place; setupLibraryBreadCrumbsForAsset(projectInfo, pathPlaceRequest.getPath()); showDocks(); } else if (!place.getIdentifier().equals(MESSAGES) && isLibraryPlace(place)) { hideDocks(); if (place.getIdentifier().equals(PROJECT_SETTINGS)) { setupLibraryBreadCrumbsForAsset(projectInfo, null); } else if (projectInfo.getProject() != null && (place.getIdentifier().equals(LibraryPlaces.PROJECT_SCREEN) || place.getIdentifier().equals(LibraryPlaces.EMPTY_PROJECT_SCREEN))) { setupLibraryBreadCrumbsForProject(projectInfo); } else if (place.getIdentifier().equals(LibraryPlaces.LIBRARY_SCREEN) || place.getIdentifier().equals(LibraryPlaces.EMPTY_LIBRARY_SCREEN)) { setupLibraryBreadCrumbs(); } } } } public void hideDocks() { if (!docksHidden) { docks.hide(); docksHidden = true; } } public void showDocks() { if (docksHidden) { if (!docksReady) { docks.setup(LibraryPlaces.LIBRARY_PERSPECTIVE, new DefaultPlaceRequest(PROJECT_EXPLORER)); docksReady = true; } docks.show(); docksHidden = false; } } private boolean isLibraryPlace(final PlaceRequest place) { return LIBRARY_PLACES.contains(place.getIdentifier()); } public void newResourceCreated(@Observes final NewResourceSuccessEvent newResourceSuccessEvent) { if (isLibraryPerspectiveOpen()) { assetDetailEvent.fire(new AssetDetailEvent(getProjectInfo(), newResourceSuccessEvent.getPath())); } } public void assetRenamedAccepted(@Observes final ConcurrentRenameAcceptedEvent concurrentRenameAcceptedEvent) { if (isLibraryPerspectiveOpen()) { final ProjectInfo projectInfo = getProjectInfo(); final ObservablePath path = concurrentRenameAcceptedEvent.getPath(); goToAsset(projectInfo, path); setupLibraryBreadCrumbsForAsset(projectInfo, path); } } public void projectDeleted(@Observes final DeleteProjectEvent deleteProjectEvent) { if (isLibraryPerspectiveOpen()) { if (deleteProjectEvent.getProject().equals(lastViewedProject)) { goToLibrary(); notificationEvent.fire(new NotificationEvent(ts.getTranslation(LibraryConstants.ProjectDeleted), NotificationEvent.NotificationType.DEFAULT)); } } } public void projectRenamed(@Observes final RenameProjectEvent renameProjectEvent) { if (isLibraryPerspectiveOpen()) { final Project activeProject = projectContext.getActiveProject(); if (renameProjectEvent.getOldProject().equals(activeProject)) { setupLibraryBreadCrumbsForAsset(new ProjectInfo(projectContext.getActiveOrganizationalUnit(), projectContext.getActiveRepository(), projectContext.getActiveBranch(), renameProjectEvent.getNewProject()), null); lastViewedProject = renameProjectEvent.getNewProject(); } } } public void assetSelected(@Observes final AssetDetailEvent assetDetails) { goToAsset(assetDetails.getProjectInfo(), assetDetails.getPath()); } public void projectContextChange() { final ProjectInfo projectInfo = new ProjectInfo(projectContext.getActiveOrganizationalUnit(), projectContext.getActiveRepository(), projectContext.getActiveBranch(), projectContext.getActiveProject()); if (isLibraryPerspectiveOpen() && projectContext.getActiveRepository() != null) { if ((libraryToolbar.getSelectedRepository() != null && !libraryToolbar.getSelectedRepository().equals(projectContext.getActiveRepository())) || (libraryToolbar.getSelectedBranch() != null && !libraryToolbar.getSelectedBranch().equals(projectContext.getActiveBranch()))) { libraryToolbar.setSelectedInfo(projectContext.getActiveOrganizationalUnit(), projectContext.getActiveRepository(), () -> { if (projectContext.getActiveProject() != null) { goToProject(projectInfo, false); } }); } else if (projectContext.getActiveProject() != null && !projectContext.getActiveProject().equals(lastViewedProject)) { goToProject(projectInfo, false); } } } private boolean isLibraryPerspectiveOpen() { return placeManager.getStatus(LIBRARY_PERSPECTIVE).equals(PlaceStatus.OPEN) || placeManager.getStatus(getLibraryPlaceRequestWithoutRefresh()).equals(PlaceStatus.OPEN); } public void onSocialFileSelected(@Observes final SocialFileSelectedEvent event) { vfsService.call(new RemoteCallback<Path>() { @Override public void callback(Path path) { explorerService.call(new RemoteCallback<URIStructureExplorerModel>() { @Override public void callback(final URIStructureExplorerModel model) { openBestSuitedScreen(event.getEventType(), path, new ProjectInfo(model.getOrganizationalUnit(), model.getRepository(), model.getRepository().getDefaultBranch(), model.getProject())); } }).getURIStructureExplorerModel(path); } }).get(event.getUri()); } private void openBestSuitedScreen(final String eventType, final Path path, final ProjectInfo projectInfo) { final PlaceRequest libraryPerspective = getLibraryPlaceRequestWithoutRefresh(); if (isRepositoryEvent(eventType)) { placeManager.goTo(REPOSITORY_STRUCTURE_SCREEN); } else if (isProjectEvent(eventType)) { placeManager.goTo(libraryPerspective); goToProject(projectInfo); } else if (path != null){ placeManager.goTo(libraryPerspective); goToProject(projectInfo, true, () -> goToAsset(projectInfo, path)); } } PlaceRequest getLibraryPlaceRequestWithoutRefresh() { final Map<String, String> params = new HashMap<>(); params.put("refresh", "false"); return new DefaultPlaceRequest(LIBRARY_PERSPECTIVE, params); } private boolean isRepositoryEvent(String eventType) { if (eventType == null || eventType.isEmpty()) { return false; } if (ExtendedTypes.NEW_REPOSITORY_EVENT.name().equals(eventType) || AssetManagementEventTypes.BRANCH_CREATED.name().equals(eventType) || AssetManagementEventTypes.REPOSITORY_CHANGE.name().equals(eventType)) { return true; } return false; } private boolean isProjectEvent(final String eventType) { return ProjectEventType.NEW_PROJECT.name().equals(eventType); } public void setupToolBar() { breadcrumbs.clearBreadcrumbsAndToolBars(LibraryPlaces.LIBRARY_PERSPECTIVE); breadcrumbs.addToolbar(LibraryPlaces.LIBRARY_PERSPECTIVE, libraryToolbar.getView().getElement()); } public void setupLibraryBreadCrumbsForOrganizationUnits() { breadcrumbs.clearBreadcrumbsAndToolBars(LibraryPlaces.LIBRARY_PERSPECTIVE); breadcrumbs.addBreadCrumb(LibraryPlaces.LIBRARY_PERSPECTIVE, translationUtils.getOrganizationalUnitAliasInPlural(), () -> goToOrganizationalUnits()); } public void setupLibraryBreadCrumbs() { setupToolBar(); breadcrumbs.addBreadCrumb(LibraryPlaces.LIBRARY_PERSPECTIVE, translationUtils.getOrganizationalUnitAliasInPlural(), () -> goToOrganizationalUnits()); breadcrumbs.addBreadCrumb(LibraryPlaces.LIBRARY_PERSPECTIVE, getSelectedOrganizationalUnit().getName(), () -> goToLibrary()); } public void setupLibraryBreadCrumbsForNewProject() { breadcrumbs.clearBreadcrumbs(LibraryPlaces.LIBRARY_PERSPECTIVE); breadcrumbs.addBreadCrumb(LibraryPlaces.LIBRARY_PERSPECTIVE, translationUtils.getOrganizationalUnitAliasInPlural(), () -> goToOrganizationalUnits()); breadcrumbs.addBreadCrumb(LibraryPlaces.LIBRARY_PERSPECTIVE, getSelectedOrganizationalUnit().getName(), () -> goToLibrary()); breadcrumbs.addBreadCrumb(LibraryPlaces.LIBRARY_PERSPECTIVE, ts.getTranslation(LibraryConstants.NewProject), () -> goToNewProject()); } public void setupLibraryBreadCrumbsForProject(final ProjectInfo projectInfo) { breadcrumbs.clearBreadcrumbs(LibraryPlaces.LIBRARY_PERSPECTIVE); breadcrumbs.addBreadCrumb(LibraryPlaces.LIBRARY_PERSPECTIVE, translationUtils.getOrganizationalUnitAliasInPlural(), () -> goToOrganizationalUnits()); breadcrumbs.addBreadCrumb(LibraryPlaces.LIBRARY_PERSPECTIVE, getSelectedOrganizationalUnit().getName(), () -> goToLibrary()); breadcrumbs.addBreadCrumb(LibraryPlaces.LIBRARY_PERSPECTIVE, projectInfo.getProject().getProjectName(), () -> goToProject(projectInfo)); } public void setupLibraryBreadCrumbsForAsset(final ProjectInfo projectInfo, final Path path) { String assetName; if (path != null) { assetName = resourceUtils.getBaseFileName(path); } else { assetName = ts.format(LibraryConstants.Settings); } breadcrumbs.clearBreadcrumbs(LibraryPlaces.LIBRARY_PERSPECTIVE); breadcrumbs.addBreadCrumb(LibraryPlaces.LIBRARY_PERSPECTIVE, translationUtils.getOrganizationalUnitAliasInPlural(), () -> goToOrganizationalUnits()); breadcrumbs.addBreadCrumb(LibraryPlaces.LIBRARY_PERSPECTIVE, getSelectedOrganizationalUnit().getName(), () -> goToLibrary()); breadcrumbs.addBreadCrumb(LibraryPlaces.LIBRARY_PERSPECTIVE, projectInfo.getProject().getProjectName(), () -> goToProject(projectInfo)); breadcrumbs.addBreadCrumb(LibraryPlaces.LIBRARY_PERSPECTIVE, assetName, () -> goToAsset(projectInfo, path)); } public void refresh(final Command callback) { translationUtils.refresh(() -> { libraryToolbar.init(() -> { setupToolBar(); if (callback != null) { callback.execute(); } }); }); } public void goToOrganizationalUnits() { if (closeAllPlacesOrNothing()) { final DefaultPlaceRequest placeRequest = new DefaultPlaceRequest(LibraryPlaces.ORGANIZATIONAL_UNITS_SCREEN); final PartDefinitionImpl part = new PartDefinitionImpl(placeRequest); part.setSelectable(false); placeManager.goTo(part, libraryPerspective.getRootPanel()); setupLibraryBreadCrumbsForOrganizationUnits(); projectContextChangeEvent.fire(new ProjectContextChangeEvent(getSelectedOrganizationalUnit())); } } public void goToLibrary() { goToLibrary(null); } public void goToLibrary(final Command callback) { libraryService.call(new RemoteCallback<Boolean>() { @Override public void callback(final Boolean hasProjects) { libraryService.call(libraryInfo -> { final PlaceRequest placeRequest = new ConditionalPlaceRequest(LibraryPlaces.LIBRARY_SCREEN) .when(p -> hasProjects) .orElse(new DefaultPlaceRequest(LibraryPlaces.EMPTY_LIBRARY_SCREEN)); final PartDefinitionImpl part = new PartDefinitionImpl(placeRequest); part.setSelectable(false); closeLibraryPlaces(); placeManager.goTo(part, libraryPerspective.getRootPanel()); setupLibraryBreadCrumbs(); hideDocks(); if (callback != null) { callback.execute(); } else { projectContextChangeEvent.fire(new ProjectContextChangeEvent(getSelectedOrganizationalUnit(), getSelectedRepository(), getSelectedBranch())); } }).getLibraryInfo(getSelectedRepository(), getSelectedBranch()); } }).hasProjects(getSelectedRepository(), getSelectedBranch()); } public void goToProject(final ProjectInfo projectInfo) { goToProject(projectInfo, true); } public void goToProject(final ProjectInfo projectInfo, final boolean fireProjectContextChangeEvent) { goToProject(projectInfo, fireProjectContextChangeEvent, null); } public void goToProject(final ProjectInfo projectInfo, final boolean fireProjectContextChangeEvent, final Command callback) { libraryService.call(hasAssets -> { final PlaceRequest projectScreen = new ConditionalPlaceRequest(LibraryPlaces.PROJECT_SCREEN) .when(p -> (Boolean) hasAssets) .orElse(new DefaultPlaceRequest(LibraryPlaces.EMPTY_PROJECT_SCREEN)); final PartDefinitionImpl part = new PartDefinitionImpl(projectScreen); part.setSelectable(false); boolean goToProject = true; if (!projectInfo.getProject().equals(lastViewedProject)) { goToProject = closeAllPlacesOrNothing(); } if (goToProject) { hideDocks(); lastViewedProject = projectInfo.getProject(); if (fireProjectContextChangeEvent) { projectContextChangeEvent.fire(new ProjectContextChangeEvent(projectInfo.getOrganizationalUnit(), projectInfo.getRepository(), projectInfo.getBranch(), projectInfo.getProject())); } placeManager.goTo(part, libraryPerspective.getRootPanel()); setupLibraryBreadCrumbsForProject(projectInfo); projectDetailEvent.fire(new ProjectDetailEvent(projectInfo)); if (callback != null) { callback.execute(); } } }).hasAssets(projectInfo.getProject()); } public void goToAsset(final ProjectInfo projectInfo, final Path path) { final PlaceRequest placeRequest = generatePlaceRequest(path); placeManager.goTo(placeRequest); if (path != null) { final ObservablePath observablePath = ((PathPlaceRequest) placeRequest).getPath(); observablePath.onRename(() -> setupLibraryBreadCrumbsForAsset(projectInfo, observablePath)); } } public void goToNewProject() { final DefaultPlaceRequest placeRequest = new DefaultPlaceRequest(LibraryPlaces.NEW_PROJECT_SCREEN); final PartDefinitionImpl part = new PartDefinitionImpl(placeRequest); part.setSelectable(false); closeLibraryPlaces(); placeManager.goTo(part, libraryPerspective.getRootPanel()); setupLibraryBreadCrumbsForNewProject(); } public void goToSettings(final ProjectInfo projectInfo) { assetDetailEvent.fire(new AssetDetailEvent(projectInfo, null)); } public void goToImportProjectWizard() { final String organizationalUnitName = projectContext.getActiveOrganizationalUnit().getName(); final String repositoryAlias = projectContext.getActiveRepository().getAlias(); final ExamplesWizard examplesWizard = examplesWizards.get(); examplesWizard.start(); examplesWizard.setDefaultTargetOrganizationalUnit(organizationalUnitName); examplesWizard.setDefaultTargetRepository(repositoryAlias); } public void goToMessages() { placeManager.goTo(MESSAGES); } public OrganizationalUnit getSelectedOrganizationalUnit() { return projectContext.getActiveOrganizationalUnit(); } public Repository getSelectedRepository() { return libraryToolbar.getSelectedRepository(); } public String getSelectedBranch() { return libraryToolbar.getSelectedBranch(); } PlaceRequest generatePlaceRequest(final Path path) { if (path == null) { return new DefaultPlaceRequest(PROJECT_SETTINGS); } return createPathPlaceRequest(path); } PathPlaceRequest createPathPlaceRequest(final Path path) { return new PathPlaceRequest(path); } void closeLibraryPlaces() { closingLibraryPlaces = true; LIBRARY_PLACES.forEach(place -> placeManager.closePlace(place)); closingLibraryPlaces = false; } boolean closeAllPlacesOrNothing() { closingLibraryPlaces = true; final boolean placesClosed = placeManager.closeAllPlacesOrNothing(); closingLibraryPlaces = false; return placesClosed; } }