blob: ab808d58c9ec521723d50a040dd266ebb3a05063 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2018 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.server.diagram.internal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.sirius.business.api.dialect.DialectManager;
import org.eclipse.sirius.business.api.modelingproject.ModelingProject;
import org.eclipse.sirius.business.api.session.Session;
import org.eclipse.sirius.business.api.session.SessionManager;
import org.eclipse.sirius.diagram.DDiagram;
import org.eclipse.sirius.services.diagram.api.SiriusDiagramMessage;
import org.eclipse.sirius.services.diagram.api.SiriusDiagramService;
import org.eclipse.sirius.viewpoint.DRepresentationDescriptor;
import org.eclipse.sirius.viewpoint.SiriusPlugin;
/**
* The Sirius server diagram service manager is used to instantiate and dispose
* the diagram services when necessary.
*
* @author sbegaudeau
*/
public class SiriusServerDiagramServiceManager {
/**
* The cache of the diagram service for a specific representation
* identifier.
*/
private Map<String, SiriusDiagramService> representation2services = new HashMap<>();
/**
* The cache of the representation identifier for a specific diagram
* service.
*/
private Map<SiriusDiagramService, String> service2representations = new HashMap<>();
/**
* The cache of session identifiers for a specific diagram service.
*/
private Map<SiriusDiagramService, List<String>> service2identifiers = new HashMap<>();
/**
* The cache of the diagram service for a specific session identifier.
*/
private Map<String, SiriusDiagramService> identifier2services = new HashMap<>();
/**
* Acquire an instance of a diagram service.
*
* @param identifier
* The identifier of the WebSocket session
* @param projectName
* The name of the project
* @param representationName
* The name of the representation
* @param callback
* The callback used for the diagram service to send data back to
* the client
* @return An instance of the diagram service or null, if the parameter do
* not match a valid diagram
*/
public SiriusDiagramService acquire(String identifier, String projectName, String representationName, Consumer<SiriusDiagramMessage> callback) {
synchronized (this.representation2services) {
String representationId = projectName + representationName;
SiriusDiagramService diagramService = this.representation2services.get(representationId);
if (diagramService == null) {
Optional<Session> optionalSession = this.getSession(projectName);
Optional<DDiagram> optionalDDiagram = optionalSession.flatMap(session -> this.getDDiagramFromSession(session, representationName));
if (optionalSession.isPresent() && optionalDDiagram.isPresent()) {
Session session = optionalSession.get();
DDiagram dDiagram = optionalDDiagram.get();
diagramService = new SiriusDiagramService(session, dDiagram, callback);
diagramService.initialize();
this.representation2services.put(representationId, diagramService);
this.service2representations.put(diagramService, representationId);
this.identifier2services.put(identifier, diagramService);
List<String> identifiers = this.service2identifiers.getOrDefault(diagramService, new ArrayList<>());
identifiers.add(identifier);
this.service2identifiers.put(diagramService, identifiers);
}
}
return diagramService;
}
}
/**
* Returns the {@link Session} found for the given project name.
*
* @param projectName
* The name of the project containing the aird
* @return The {@link Session} found or an empty optional
*/
private Optional<Session> getSession(String projectName) {
// @formatter:off
Optional<IProject> optionalProject = Optional.of(ResourcesPlugin.getWorkspace().getRoot().getProject(projectName));
Optional<ModelingProject> optionalModelingProject = optionalProject.filter(ModelingProject::hasModelingProjectNature)
.map(iProject -> ModelingProject.asModelingProject(iProject).get());
return optionalModelingProject.map(modelingProject -> {
Session session = modelingProject.getSession();
if (session == null) {
URI sessionResourceURI = modelingProject.getMainRepresentationsFileURI(new NullProgressMonitor()).get();
session = SessionManager.INSTANCE.openSession(sessionResourceURI , new NullProgressMonitor(), SiriusPlugin.getDefault().getUiCallback());
}
return session;
});
// @formatter:on
}
/**
* Returns the {@link DDiagram} found for the given {@link Session} and the
* representation name.
*
* @param session
* The {@link Session}
* @param representationName
* The name of the {@link DDiagram}
* @return The {@link DDiagram} found or an empty optional
*/
private Optional<DDiagram> getDDiagramFromSession(Session session, String representationName) {
Collection<DRepresentationDescriptor> representations = DialectManager.INSTANCE.getAllRepresentationDescriptors(session);
// @formatter:off
Optional<DDiagram> optionalDDiagram = representations.stream()
.filter(repDesc->repDesc.getRepresentation() instanceof DDiagram)
.filter(repDesc -> {
return Optional.ofNullable(representationName).orElse("").equals(repDesc.getName()); //$NON-NLS-1$
})
.map(repDesc->(DDiagram) repDesc.getRepresentation())
.findFirst();
// @formatter:on
return optionalDDiagram;
}
/**
* Release the diagram services used by the given session identifier.
*
* @param identifier
* The identifier of the session
*/
public void release(String identifier) {
synchronized (this.representation2services) {
Optional<SiriusDiagramService> optionalDiagramService = Optional.ofNullable(this.identifier2services.remove(identifier));
optionalDiagramService.ifPresent(diagramService -> {
this.service2identifiers.remove(diagramService);
String representationId = this.service2representations.remove(diagramService);
this.representation2services.remove(representationId);
diagramService.dispose();
});
}
}
}