/* * Copyright 2012 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.drools.workbench.screens.testscenario.backend.server; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Event; import javax.inject.Inject; import javax.inject.Named; import org.drools.workbench.models.datamodel.imports.Import; import org.drools.workbench.models.datamodel.imports.Imports; import org.drools.workbench.models.datamodel.oracle.ModelField; import org.drools.workbench.models.datamodel.oracle.PackageDataModelOracle; import org.drools.workbench.models.testscenarios.backend.util.ScenarioXMLPersistence; import org.drools.workbench.models.testscenarios.shared.Scenario; import org.drools.workbench.screens.testscenario.model.TestScenarioModelContent; import org.drools.workbench.screens.testscenario.model.TestScenarioResult; import org.drools.workbench.screens.testscenario.service.ScenarioTestEditorService; import org.guvnor.common.services.backend.config.SafeSessionInfo; import org.guvnor.common.services.backend.exceptions.ExceptionUtilities; import org.guvnor.common.services.backend.util.CommentedOptionFactory; import org.guvnor.common.services.project.model.Package; import org.guvnor.common.services.shared.metadata.model.Metadata; import org.guvnor.common.services.shared.metadata.model.Overview; import org.jboss.errai.bus.server.annotations.Service; import org.jboss.errai.security.shared.api.identity.User; import org.kie.workbench.common.services.backend.service.KieService; import org.kie.workbench.common.services.datamodel.backend.server.DataModelOracleUtilities; import org.kie.workbench.common.services.datamodel.backend.server.service.DataModelService; import org.kie.workbench.common.services.datamodel.model.PackageDataModelOracleBaselinePayload; import org.kie.workbench.common.services.shared.project.KieProjectService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.uberfire.backend.server.util.Paths; import org.uberfire.backend.vfs.Path; import org.uberfire.ext.editor.commons.service.CopyService; import org.uberfire.ext.editor.commons.service.DeleteService; import org.uberfire.ext.editor.commons.service.RenameService; import org.uberfire.io.IOService; import org.uberfire.java.nio.file.FileAlreadyExistsException; import org.uberfire.rpc.SessionInfo; import org.uberfire.workbench.events.ResourceOpenedEvent; @Service @ApplicationScoped public class ScenarioTestEditorServiceImpl extends KieService<TestScenarioModelContent> implements ScenarioTestEditorService { private Logger logger = LoggerFactory.getLogger(ScenarioTestEditorServiceImpl.class); @Inject @Named("ioStrategy") private IOService ioService; @Inject private CopyService copyService; @Inject private DeleteService deleteService; @Inject private RenameService renameService; @Inject private Event<ResourceOpenedEvent> resourceOpenedEvent; @Inject private DataModelService dataModelService; @Inject private ScenarioRunnerService scenarioRunner; @Inject private CommentedOptionFactory commentedOptionFactory; private SafeSessionInfo safeSessionInfo; public ScenarioTestEditorServiceImpl() { } @Inject public ScenarioTestEditorServiceImpl(final SessionInfo sessionInfo) { safeSessionInfo = new SafeSessionInfo(sessionInfo); } @Override public Path create(final Path context, final String fileName, final Scenario content, final String comment) { try { final org.uberfire.java.nio.file.Path nioPath = Paths.convert(context).resolve(fileName); final Path newPath = Paths.convert(nioPath); if (ioService.exists(nioPath)) { throw new FileAlreadyExistsException(nioPath.toString()); } ioService.write(nioPath, ScenarioXMLPersistence.getInstance().marshal(content), commentedOptionFactory.makeCommentedOption(comment)); return newPath; } catch (Exception e) { throw ExceptionUtilities.handleException(e); } } @Override public Scenario load(final Path path) { try { final String content = ioService.readAllString(Paths.convert(path)); final Scenario scenario = ScenarioXMLPersistence.getInstance().unmarshal(content); scenario.setName(path.getFileName()); return scenario; } catch (final Exception e) { logger.error("Unable to unmarshal content. Returning an empty Test Scenario.", e); final Package resolvedPackage = projectService.resolvePackage(path); final Scenario scenario = new Scenario(); if (resolvedPackage != null) { scenario.setPackageName(resolvedPackage.getPackageName()); } scenario.setImports(new Imports()); return scenario; } } @Override public Path save(final Path resource, final Scenario content, final Metadata metadata, final String comment) { try { Metadata currentMetadata = metadataService.getMetadata(resource); ioService.write(Paths.convert(resource), ScenarioXMLPersistence.getInstance().marshal(content), metadataService.setUpAttributes(resource, metadata), commentedOptionFactory.makeCommentedOption(comment)); fireMetadataSocialEvents(resource, currentMetadata, metadata); return resource; } catch (Exception e) { throw ExceptionUtilities.handleException(e); } } @Override public void delete(final Path path, final String comment) { try { deleteService.delete(path, comment); } catch (Exception e) { throw ExceptionUtilities.handleException(e); } } @Override public Path rename(final Path path, final String newName, final String comment) { try { return renameService.rename(path, newName, comment); } catch (Exception e) { throw ExceptionUtilities.handleException(e); } } @Override public Path copy(final Path path, final String newName, final String comment) { try { return copyService.copy(path, newName, comment); } catch (Exception e) { throw ExceptionUtilities.handleException(e); } } @Override public Path copy(final Path path, final String newName, final Path targetDirectory, final String comment) { try { return copyService.copy(path, newName, targetDirectory, comment); } catch (Exception e) { throw ExceptionUtilities.handleException(e); } } @Override public TestScenarioModelContent loadContent(Path path) { return super.loadContent(path); } @Override protected TestScenarioModelContent constructContent(Path path, Overview overview) { final Scenario scenario = load(path); final String packageName = projectService.resolvePackage(path).getPackageName(); final PackageDataModelOracle dataModelOracle = getDataModel(path); final PackageDataModelOracleBaselinePayload dataModel = new PackageDataModelOracleBaselinePayload(); final Set<String> usedFullyQualifiedClassNames = getUsedFullyQualifiedClassNames(scenario, dataModelOracle); DataModelOracleUtilities.populateDataModel(dataModelOracle, dataModel, usedFullyQualifiedClassNames); //Signal opening to interested parties resourceOpenedEvent.fire(new ResourceOpenedEvent(path, safeSessionInfo)); return new TestScenarioModelContent(scenario, overview, packageName, dataModel); } @Override public TestScenarioResult runScenario(final String userName, final Path path, final Scenario scenario) { final Imports existingScenarioImports = new Imports(scenario.getImports().getImports()); try { addDependentImportsToScenario(scenario, path); final TestScenarioResult result = scenarioRunner.run(userName, scenario, projectService.resolveProject(path)); return result; } catch (final Exception e) { throw ExceptionUtilities.handleException(e); } finally { scenario.setImports(existingScenarioImports); } } void addDependentImportsToScenario(final Scenario scenario, final Path path) { final PackageDataModelOracle dataModel = getDataModel(path); final Set<String> usedFullyQualifiedClassNames = getUsedFullyQualifiedClassNames(scenario, dataModel); for (String className : usedFullyQualifiedClassNames) { final Import imp = new Import(className); final List<Import> scenarioImports = scenario.getImports().getImports(); if (!scenarioImports.contains(imp)) { scenarioImports.add(imp); } } } private PackageDataModelOracle getDataModel(final Path path) { return dataModelService.getDataModel(path); } private Set<String> getUsedFullyQualifiedClassNames(final Scenario scenario, final PackageDataModelOracle dataModelOracle) { return new HashSet<String>() {{ addAll(getFullyQualifiedClassNamesUsedByModel(scenario, dataModelOracle)); addAll(getFullyQualifiedClassNamesUsedByGlobals(dataModelOracle)); }}; } private Set<String> getFullyQualifiedClassNamesUsedByModel(final Scenario scenario, final PackageDataModelOracle dataModelOracle) { final Set<String> fullyQualifiedClassNames = new HashSet<>(); for (String fullyQualifiedClassName : getFullyQualifiedClassNameFromScenario(scenario)) { final ModelField[] modelFields = dataModelOracle.getProjectModelFields().get(fullyQualifiedClassName); if (modelFields != null) { for (ModelField modelField : modelFields) { fullyQualifiedClassNames.add(modelField.getClassName()); } fullyQualifiedClassNames.add(fullyQualifiedClassName); } } return fullyQualifiedClassNames; } private List<String> getFullyQualifiedClassNameFromScenario(final Scenario scenario) { final TestScenarioModelVisitor testScenarioModelVisitor = new TestScenarioModelVisitor(scenario); return new ArrayList<String>() {{ addAll(testScenarioModelVisitor.visit()); addAll(scenario.getImports().getImports().stream().collect(Collectors.mapping(Import::getType, Collectors.toList()))); }}; } private Collection<String> getFullyQualifiedClassNamesUsedByGlobals(final PackageDataModelOracle dataModelOracle) { return dataModelOracle.getPackageGlobals().values(); } }