blob: 9b7fa705b83bf720a8b7615c2ad02015b941e137 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2019 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.services.graphql.internal.schema.mutation;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.transaction.RecordingCommand;
import org.eclipse.sirius.business.api.dialect.DialectManager;
import org.eclipse.sirius.business.api.session.Session;
import org.eclipse.sirius.services.common.api.SiriusServicesCommonOptionalUtils;
import org.eclipse.sirius.services.graphql.workspace.api.WorkspaceSchemaConstants;
import org.eclipse.sirius.viewpoint.description.RepresentationDescription;
import org.eclipse.sirius.viewpoint.description.Viewpoint;
import graphql.Scalars;
import graphql.schema.DataFetcher;
import graphql.schema.GraphQLArgument;
import graphql.schema.GraphQLFieldDefinition;
import graphql.schema.GraphQLNonNull;
import graphql.schema.GraphQLTypeReference;
/**
* Used to create the creatRepresentation field.
*
* @author sbegaudeau
*/
public final class CreateRepresentationField {
/**
* The name of the createRepresentation field.
*/
private static final String CREATE_REPRESENTATION_FIELD = "createRepresentation"; //$NON-NLS-1$
/**
* The name of the resourcePath argument.
*/
private static final String RESOURCE_PATH_ARG = "resourcePath"; //$NON-NLS-1$
/**
* The name of the description argument.
*/
private static final String DESCRIPTION_ARG = "description"; //$NON-NLS-1$
/**
* The constructor.
*/
private CreateRepresentationField() {
// Prevent instantiation
}
/**
* Returns the createRepresentation field.
*
* @return The createRepresentation field
*/
public static GraphQLFieldDefinition build() {
// @formatter:off
return GraphQLFieldDefinition.newFieldDefinition()
.name(CREATE_REPRESENTATION_FIELD)
.argument(ProjectNameArgument.build())
.argument(CreateRepresentationField.getResourcePathArgument())
.argument(CreateRepresentationField.getDescriptionArgument())
.type(new GraphQLTypeReference(WorkspaceSchemaConstants.PROJECT_TYPE))
.dataFetcher(CreateRepresentationField.getCreateRepresentationDataFetcher())
.build();
// @formatter:on
}
/**
* Returns the resourcePath argument.
*
* @return The resourcePath argument
*/
private static GraphQLArgument getResourcePathArgument() {
// @formatter:off
return GraphQLArgument.newArgument()
.name(RESOURCE_PATH_ARG)
.type(new GraphQLNonNull(Scalars.GraphQLString))
.build();
// @formatter:on
}
/**
* Returns the description argument.
*
* @return The description argument
*/
private static GraphQLArgument getDescriptionArgument() {
// @formatter:off
return GraphQLArgument.newArgument()
.name(DESCRIPTION_ARG)
.type(new GraphQLNonNull(new GraphQLTypeReference(RepresentationCreationDescriptionTypesProvider.REPRESENTATION_CREATION_DESCRIPTION_TYPE)))
.build();
// @formatter:on
}
/**
* Returns the createRepresentation data fetcher.
*
* @return The createRepresentation data fetcher
*/
private static DataFetcher<IProject> getCreateRepresentationDataFetcher() {
// @formatter:off
return environment -> {
Optional<String> optionalProjectName = Optional.of(environment.getArgument(ProjectNameArgument.PROJECT_NAME_ARG))
.filter(String.class::isInstance)
.map(String.class::cast);
Optional<IProject> optionalProject = optionalProjectName.map(ResourcesPlugin.getWorkspace().getRoot()::getProject);
Optional<Session> optionalSession = optionalProject.flatMap(SiriusServicesCommonOptionalUtils::toSession);
Function<IProject, Optional<IFile>> getFile = iProject -> Optional.of(environment.getArgument(RESOURCE_PATH_ARG))
.filter(String.class::isInstance)
.map(String.class::cast)
.map(Path::new)
.map(iProject::getFile);
Optional<IFile> optionalFile = optionalProject.flatMap(getFile);
Optional<Resource> optionalResource = optionalFile.flatMap(iFile -> {
return optionalSession.flatMap(session -> SiriusServicesCommonOptionalUtils.toResource(session, iFile));
});
Map<String, String> description = environment.<Map<String, String>>getArgument(DESCRIPTION_ARG);
String viewpointIdentifier = description.get(RepresentationCreationDescriptionTypesProvider.VIEWPOINT_IDENTIFIER_FIELD);
String representationIdentifier = description.get(RepresentationCreationDescriptionTypesProvider.REPRESENTATION_IDENTIFIER_FIELD);
String eObjectFragment = description.get(RepresentationCreationDescriptionTypesProvider.EOBJECT_FRAGMENT_FIELD);
String name = description.get(RepresentationCreationDescriptionTypesProvider.NAME_FIELD);
Optional<Viewpoint> optionalViewpoint = optionalSession.flatMap(session -> {
return session.getSelectedViewpoints(false).stream()
.filter(viewpoint -> viewpointIdentifier.equals(viewpoint.getName()))
.findFirst();
});
Optional<RepresentationDescription> optionalRepresentationDescription = optionalViewpoint.flatMap(viewpoint -> {
return viewpoint.getOwnedRepresentations().stream()
.filter(representationDescription -> representationIdentifier.equals(representationDescription.getName()))
.findFirst();
});
Optional<EObject> optionalEObject = optionalResource.map(resource -> resource.getEObject(eObjectFragment));
optionalSession.ifPresent(session -> {
optionalRepresentationDescription.ifPresent(representationDescription -> {
optionalEObject.ifPresent(eObject -> {
boolean canCreate = DialectManager.INSTANCE.canCreate(eObject, representationDescription, true);
if (canCreate) {
CreateRepresentationField.createRepresentation(session, representationDescription, name, eObject);
}
});
});
});
return optionalProject.orElse(null);
};
// @formatter:on
}
/**
* Creates the representation using a recording command.
*
* @param session
* The session
* @param representationDescription
* The description of the representation
* @param name
* The name of the representation
* @param eObject
* The EObject used as the root of the representation
*/
private static void createRepresentation(Session session, RepresentationDescription representationDescription, String name, EObject eObject) {
RecordingCommand command = new RecordingCommand(session.getTransactionalEditingDomain()) {
@Override
protected void doExecute() {
DialectManager.INSTANCE.createRepresentation(name, eObject, representationDescription, session, new NullProgressMonitor());
}
};
session.getTransactionalEditingDomain().getCommandStack().execute(command);
}
}