From 7bece2b09531e12c14082f292e13b6f943a0c532 Mon Sep 17 00:00:00 2001 From: Michael Wurster Date: Mon, 25 Jan 2021 16:49:41 +0100 Subject: [PATCH] Enhance EDMM integration - Transformation check based on rule system - Adaptation proposals - Trigger transformation from TopoMod Co-authored-by: Leonardo Frioli Signed-off-by: Michael Wurster --- .mailmap | 1 + NOTICE | 3 +- org.eclipse.winery.common/pom.xml | 2 +- org.eclipse.winery.crawler/pom.xml | 2 +- org.eclipse.winery.edmm/pom.xml | 9 +- .../org/eclipse/winery/edmm/EdmmManager.java | 5 +- .../winery/edmm/TransformationManager.java | 55 ++ .../winery/edmm/model/EdmmConverter.java | 23 +- .../winery/edmm/plugins/PluginManager.java | 113 +++ .../eclipse/winery/edmm/utils/ZipUtility.java | 58 ++ .../winery/edmm/EdmmDependantTest.java | 3 +- .../org/eclipse/winery/edmm/EdmmTests.java | 65 ++ .../eclipse/winery/edmm/EdmmUtilsTest.java | 2 +- .../winery/edmm/JsonBasedEdmmManagerTest.java | 3 +- .../src/test/resources/edmmMapping.json | 0 .../src/app/canvas/canvas.component.ts | 60 +- .../edmm-replacement-rules.component.html | 28 + .../edmm-replacement-rules.component.ts | 214 +++++ .../edmmTransformationCheck.component.css | 10 +- .../edmmTransformationCheck.component.html | 41 +- .../edmmTransformationCheck.component.ts | 45 +- .../edmmTransformationCheck.service.ts | 51 +- .../src/app/palette/palette.component.html | 4 +- .../src/app/palette/palette.component.ts | 22 +- .../app/services/manage-topology.service.ts | 76 ++ .../topologymodeler/src/app/winery.module.ts | 6 +- org.eclipse.winery.repository.rest/pom.xml | 21 +- .../winery/repository/rest/RestUtils.java | 13 +- .../_support/GenericFileResource.java | 21 +- .../rest/resources/edmm/EdmmResource.java | 263 ++++++ .../ServiceTemplateResource.java | 8 +- .../rest/resources/edmm/EdmmResourceTest.java | 64 ++ .../petclinic-cloud.check-model-support.json | 868 ++++++++++++++++++ .../petclinic-iaas.check-model-support.json | 107 +++ .../edmm/petclinic-iaas.one-to-one-map.json | 21 + org.eclipse.winery.repository/pom.xml | 8 +- pom.xml | 2 + 37 files changed, 2169 insertions(+), 128 deletions(-) create mode 100644 org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/TransformationManager.java create mode 100644 org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/plugins/PluginManager.java create mode 100644 org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/utils/ZipUtility.java create mode 100644 org.eclipse.winery.edmm/src/test/java/org/eclipse/winery/edmm/EdmmTests.java rename {org.eclipse.winery.repository => org.eclipse.winery.edmm}/src/test/resources/edmmMapping.json (100%) create mode 100644 org.eclipse.winery.frontends/app/topologymodeler/src/app/edmmTransformationCheck/edmm-replacement-rules/edmm-replacement-rules.component.html create mode 100644 org.eclipse.winery.frontends/app/topologymodeler/src/app/edmmTransformationCheck/edmm-replacement-rules/edmm-replacement-rules.component.ts create mode 100644 org.eclipse.winery.frontends/app/topologymodeler/src/app/services/manage-topology.service.ts create mode 100644 org.eclipse.winery.repository.rest/src/main/java/org/eclipse/winery/repository/rest/resources/edmm/EdmmResource.java create mode 100644 org.eclipse.winery.repository.rest/src/test/java/org/eclipse/winery/repository/rest/resources/edmm/EdmmResourceTest.java create mode 100644 org.eclipse.winery.repository.rest/src/test/resources/edmm/petclinic-cloud.check-model-support.json create mode 100644 org.eclipse.winery.repository.rest/src/test/resources/edmm/petclinic-iaas.check-model-support.json create mode 100644 org.eclipse.winery.repository.rest/src/test/resources/edmm/petclinic-iaas.one-to-one-map.json diff --git a/.mailmap b/.mailmap index 954143da36..c5b0154845 100644 --- a/.mailmap +++ b/.mailmap @@ -13,6 +13,7 @@ Michael Wurster Latife Sen Ana Cristina Franco da Silva Pascal Hirmer +Leonardo Frioli Dominik Voigt Ghareeb Falazi Björn Müller diff --git a/NOTICE b/NOTICE index 716b8028ad..f3353f2ba6 100644 --- a/NOTICE +++ b/NOTICE @@ -52,7 +52,7 @@ Copyright (c) 2017 Huixin Liu Copyright (c) 2017-2020 Karoline Saatkamp Copyright (c) 2017 Marvin Wohlfarth Copyright (c) 2017 Michael Falkenthal -Copyright (c) 2017-2020 Michael Wurster +Copyright (c) 2017-2021 Michael Wurster Copyright (c) 2017 Nick Fode Copyright (c) 2017 Latife Sen Copyright (c) 2017 Ruzica Jozin @@ -80,6 +80,7 @@ Copyright (c) 2019 Sascha Zeller Copyright (c) 2019-2020 Tobias Mathony Copyright (c) 2019 Yannik Dietrich Copyright (c) 2019 Yuye Tong +Copyright (c) 2020 Leonardo Frioli Copyright (c) 2019-2020 Felix Burk Copyright (c) 2019-2020 Johannes Hepp diff --git a/org.eclipse.winery.common/pom.xml b/org.eclipse.winery.common/pom.xml index 2dae3fc98b..31f3434291 100644 --- a/org.eclipse.winery.common/pom.xml +++ b/org.eclipse.winery.common/pom.xml @@ -45,7 +45,7 @@ org.yaml snakeyaml - 1.17 + ${snakeyaml.version} com.fasterxml.jackson.core diff --git a/org.eclipse.winery.crawler/pom.xml b/org.eclipse.winery.crawler/pom.xml index bc703c359d..6425d05865 100644 --- a/org.eclipse.winery.crawler/pom.xml +++ b/org.eclipse.winery.crawler/pom.xml @@ -38,7 +38,7 @@ org.yaml snakeyaml - 1.21 + ${snakeyaml.version} org.antlr diff --git a/org.eclipse.winery.edmm/pom.xml b/org.eclipse.winery.edmm/pom.xml index eec37e38a7..d6fa7f2945 100644 --- a/org.eclipse.winery.edmm/pom.xml +++ b/org.eclipse.winery.edmm/pom.xml @@ -35,7 +35,7 @@ com.github.UST-EDMM.edmm edmm-core - v1.0.8 + v1.0.9 org.eclipse.winery @@ -58,6 +58,12 @@ ${junit.jupiter.version} test + + org.junit.jupiter + junit-jupiter-params + ${junit.jupiter.version} + test + io.github.adr e-adr @@ -70,5 +76,4 @@ - diff --git a/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/EdmmManager.java b/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/EdmmManager.java index 3a8b929ad1..d4c21210b0 100644 --- a/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/EdmmManager.java +++ b/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/EdmmManager.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019-2020 Contributors to the Eclipse Foundation + * Copyright (c) 2019-2021 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -11,7 +11,6 @@ * * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 *******************************************************************************/ - package org.eclipse.winery.edmm; import java.util.HashMap; @@ -33,7 +32,7 @@ static EdmmManager forRepository(IRepository repo) { RepositoryFileReference ref = BackendUtils.getRefOfJsonConfiguration(new EdmmMappingsId()); return new JsonBasedEdmmManager(repo.ref2AbsolutePath(ref).toFile()); } - + List getOneToOneMappings(); void setOneToOneMappings(List list); diff --git a/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/TransformationManager.java b/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/TransformationManager.java new file mode 100644 index 0000000000..ce65002c5b --- /dev/null +++ b/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/TransformationManager.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2021 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Apache Software License 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 + *******************************************************************************/ +package org.eclipse.winery.edmm; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.UUID; + +import org.eclipse.winery.edmm.plugins.PluginManager; +import org.eclipse.winery.edmm.utils.ZipUtility; + +import io.github.edmm.core.parser.EntityGraph; +import io.github.edmm.core.plugin.PluginService; +import io.github.edmm.core.transformation.TransformationContext; +import io.github.edmm.core.transformation.TransformationService; +import io.github.edmm.model.DeploymentModel; + +public class TransformationManager { + + public File transform(EntityGraph entityGraph, String target, String wineryRepository) throws Exception { + PluginService pluginService = PluginManager.getInstance() + .getPluginService(); + TransformationService transformationService = new TransformationService(pluginService); + + // getting the model from the graph + DeploymentModel deploymentModel = new DeploymentModel(UUID.randomUUID().toString(), entityGraph); + + // the paths of the artifacts or operation files start from the root directory + File sourceDirectory = Paths.get(wineryRepository).toFile(); + File targetDirectory = Files.createTempDirectory(target + "-").toFile(); + + TransformationContext transformationContext = transformationService.createContext(deploymentModel, target, sourceDirectory, targetDirectory); + transformationService.start(transformationContext); + // throws an exception if the transformation wasn't successful + transformationContext.throwExceptionIfErrorState(); + + Path zipPath = Paths.get(System.getProperty("java.io.tmpdir")).resolve(target + ".zip"); + ZipUtility.pack(targetDirectory.toPath(), zipPath); + + return zipPath.toFile(); + } +} diff --git a/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/model/EdmmConverter.java b/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/model/EdmmConverter.java index 30baa4289c..7cdafd3606 100644 --- a/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/model/EdmmConverter.java +++ b/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/model/EdmmConverter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019-2020 Contributors to the Eclipse Foundation + * Copyright (c) 2019-2021 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -100,7 +100,7 @@ public EntityGraph transform(TServiceTemplate serviceTemplate) { } private void createRelation(TRelationshipTemplate relationship, EntityGraph entityGraph) { - EntityId sourceComponentEntityId = EntityGraph.COMPONENTS.extend(relationship.getSourceElement().getRef().getName()); + EntityId sourceComponentEntityId = EntityGraph.COMPONENTS.extend(relationship.getSourceElement().getRef().getId()); // the entity will always be in the graph since we first transform the NodeTemplates entityGraph.getEntity(sourceComponentEntityId).ifPresent(entity -> { EntityId relationTypeEntityId = createType( @@ -120,7 +120,7 @@ private void createRelation(TRelationshipTemplate relationship, EntityGraph enti entityGraph.addEntity(new MappingEntity(relationEntityId, entityGraph)); createProperties(relationship, relationEntityId, entityGraph); } else { - String targetComponent = relationship.getTargetElement().getRef().getName(); + String targetComponent = relationship.getTargetElement().getRef().getId(); entityGraph.addEntity(new ScalarEntity(targetComponent, relationEntityId, entityGraph)); } }); @@ -128,7 +128,7 @@ private void createRelation(TRelationshipTemplate relationship, EntityGraph enti private void createNode(TNodeTemplate nodeTemplate, EntityGraph entityGraph) { // create the component inside the topology. - EntityId componentNodeId = EntityGraph.COMPONENTS.extend(nodeTemplate.getName()); + EntityId componentNodeId = EntityGraph.COMPONENTS.extend(nodeTemplate.getId()); entityGraph.addEntity(new MappingEntity(componentNodeId, entityGraph)); // add the type to the model @@ -161,14 +161,8 @@ private void createArtifact(TNodeTemplate nodeTemplate, EntityId componentNodeId EntityId artifactEntityId = artifactsEntityId.extend( artifact.getArtifactType().getLocalPart().toLowerCase() ); - + createPathReferenceEntity(entityGraph, path, artifactEntityId); - - entityGraph.addEntity(new ScalarEntity( - path != null && this.useAbsolutePaths ? Environments.getInstance().getRepositoryConfig().getRepositoryRoot() + "/" + path : path, - artifactEntityId, - entityGraph - )); } } } @@ -313,7 +307,8 @@ private String getImplementationForOperation(TEntityTypeImplementation implement if (artifacts.size() == 1 && artifacts.get(0).getArtifactRef() != null) { TArtifactTemplate artifactTemplate = artifactTemplates.get(artifacts.get(0).getArtifactRef()); - if (artifactTemplate.getArtifactReferences().getArtifactReference().size() > 0) { + if (artifactTemplate.getArtifactReferences() != null && + artifactTemplate.getArtifactReferences().getArtifactReference().size() > 0) { return artifactTemplate.getArtifactReferences().getArtifactReference().get(0).getReference(); } } @@ -321,7 +316,9 @@ private String getImplementationForOperation(TEntityTypeImplementation implement for (TImplementationArtifacts.ImplementationArtifact artifact : artifacts) { if (artifact.getOperationName().equals(operationName)) { TArtifactTemplate artifactTemplate = artifactTemplates.get(artifact.getArtifactRef()); - if (artifactTemplate != null && artifactTemplate.getArtifactReferences().getArtifactReference().size() > 0) { + if (artifactTemplate != null && + artifactTemplate.getArtifactReferences() != null && + artifactTemplate.getArtifactReferences().getArtifactReference().size() > 0) { return artifactTemplate.getArtifactReferences().getArtifactReference().get(0).getReference(); } } diff --git a/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/plugins/PluginManager.java b/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/plugins/PluginManager.java new file mode 100644 index 0000000000..8ce525739b --- /dev/null +++ b/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/plugins/PluginManager.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright (c) 2021 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Apache Software License 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 + *******************************************************************************/ + +package org.eclipse.winery.edmm.plugins; + +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import io.github.edmm.core.plugin.PluginService; +import io.github.edmm.core.plugin.TransformationPlugin; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class PluginManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(PluginManager.class); + private static PluginManager instance; + + private final List> pluginsList = new ArrayList<>(); + + private PluginManager() { + initPlugins(); + } + + public static PluginManager getInstance() { + if (instance == null) { + instance = new PluginManager(); + } + return instance; + } + + public PluginService getPluginService() { + return new PluginService(pluginsList, new ArrayList<>()); + } + + /** + * Init the plugins lists with the plugins specified in the pluginContext.xml file in the transformation-framework + * package + */ + private void initPlugins() { + for (String classpath : getPluginsClassPaths()) { + TransformationPlugin plugin; + // the plugin are initialized by reflection + try { + Class pluginClass = Class.forName(classpath); + Constructor constructor = pluginClass.getConstructor(); + plugin = (TransformationPlugin) constructor.newInstance(); + pluginsList.add(plugin); + } catch (Exception e) { + // just the single plugin won't work + LOGGER.error("Plugin" + classpath + "initialization failed", e); + } + } + } + + /** + * Read the pluginContext configuration file + * + * @return a list containing the plugins classpaths + */ + private List getPluginsClassPaths() { + List pluginsClassPaths = new ArrayList<>(); + Document xmlPluginConfigDocument; + + // opening the file in the edmm.core package + try { + InputStream pluginsInputStream = this.getClass() + .getClassLoader() + .getResourceAsStream("pluginContext.xml"); + + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + xmlPluginConfigDocument = documentBuilder.parse(pluginsInputStream); + } catch (Exception e) { + LOGGER.error("Plugin file reading failed", e); + // returns an empty list, no plugins will be initialized + return pluginsClassPaths; + } + + // the plugins are listed with the tag name 'bean' + NodeList pluginsNodeList = xmlPluginConfigDocument.getElementsByTagName("bean"); + for (int i = 0; i < pluginsNodeList.getLength(); i++) { + Node plugin = pluginsNodeList.item(i); + String classpath = plugin.getAttributes().getNamedItem("class").getNodeValue(); + pluginsClassPaths.add(classpath); + } + + return pluginsClassPaths; + } + + public List> getPluginsList() { + return pluginsList; + } +} diff --git a/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/utils/ZipUtility.java b/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/utils/ZipUtility.java new file mode 100644 index 0000000000..6a3da1644c --- /dev/null +++ b/org.eclipse.winery.edmm/src/main/java/org/eclipse/winery/edmm/utils/ZipUtility.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2021 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Apache Software License 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 + *******************************************************************************/ +package org.eclipse.winery.edmm.utils; + +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import io.github.edmm.utils.Compress; + +public class ZipUtility { + + public static void pack(Path sourcePath, Path destPath) { + Compress.zip(sourcePath, destPath); + } + + /** + * @param zipFilePath the Path of the zip file to unpack + * @param destDirPath the Path of the directory where we want the unzipped files, if the direcory exists it will be + * overwritten + * @return it return destDirPath + */ + public static Path unpack(Path zipFilePath, Path destDirPath) throws IOException { + if (Files.exists(destDirPath)) { + Files.delete(destDirPath); + } + Files.createDirectory(destDirPath); + + ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipFilePath.toFile())); + + ZipEntry zipEntry = zipInputStream.getNextEntry(); + while (zipEntry != null) { + + Path newFile = destDirPath.resolve(zipEntry.getName()); + Files.createDirectories(newFile.getParent()); + Files.copy(zipInputStream, newFile); + zipEntry = zipInputStream.getNextEntry(); + } + zipInputStream.closeEntry(); + zipInputStream.close(); + + return destDirPath; + } +} diff --git a/org.eclipse.winery.edmm/src/test/java/org/eclipse/winery/edmm/EdmmDependantTest.java b/org.eclipse.winery.edmm/src/test/java/org/eclipse/winery/edmm/EdmmDependantTest.java index aa40f06545..0225ae39a4 100644 --- a/org.eclipse.winery.edmm/src/test/java/org/eclipse/winery/edmm/EdmmDependantTest.java +++ b/org.eclipse.winery.edmm/src/test/java/org/eclipse/winery/edmm/EdmmDependantTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2020 Contributors to the Eclipse Foundation + * Copyright (c) 2020-2021 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -95,6 +95,7 @@ void setup() { WinerysPropertiesDefinition wpd = new WinerysPropertiesDefinition(); wpd.setPropertyDefinitions(kvList); ModelUtilities.replaceWinerysPropertiesDefinition(nodeType3, wpd); + nodeType3.setProperties(wpd); nodeTypes.put(nodeType3QName, nodeType3); QName nodeType4QName = QName.valueOf("{" + NAMESPACE + "}" + "test_node_type_4"); diff --git a/org.eclipse.winery.edmm/src/test/java/org/eclipse/winery/edmm/EdmmTests.java b/org.eclipse.winery.edmm/src/test/java/org/eclipse/winery/edmm/EdmmTests.java new file mode 100644 index 0000000000..d7ec7c2dbe --- /dev/null +++ b/org.eclipse.winery.edmm/src/test/java/org/eclipse/winery/edmm/EdmmTests.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2021 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Apache Software License 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 + *******************************************************************************/ +package org.eclipse.winery.edmm; + +import java.io.InputStream; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.eclipse.winery.edmm.plugins.PluginManager; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; + +public class EdmmTests { + + protected static final Logger LOGGER = LoggerFactory.getLogger(EdmmTests.class); + + @Test + public void testPluginListEmpty() { + // testing that the list is not empty + PluginManager pluginManager = PluginManager.getInstance(); + Assertions.assertFalse(pluginManager.getPluginsList().isEmpty()); + } + + @Test + public void testPluginListSize() { + // testing that the list size matches with the decleared plugins in the xml file + PluginManager pluginManager = PluginManager.getInstance(); + + Document xmlPluginConfigDocument; + // checking if the + try { + InputStream pluginsInputStream = this.getClass() + .getClassLoader() + .getResourceAsStream("pluginContext.xml"); + + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + xmlPluginConfigDocument = documentBuilder.parse(pluginsInputStream); + + NodeList pluginsNodeList = xmlPluginConfigDocument.getElementsByTagName("bean"); + int pluginsNodeListLen = pluginsNodeList.getLength(); + + Assertions.assertEquals(pluginsNodeListLen, pluginManager.getPluginsList().size()); + } catch (Exception e) { + Assertions.fail(); + } + } +} diff --git a/org.eclipse.winery.edmm/src/test/java/org/eclipse/winery/edmm/EdmmUtilsTest.java b/org.eclipse.winery.edmm/src/test/java/org/eclipse/winery/edmm/EdmmUtilsTest.java index 63e0bda7de..6efff8aac1 100644 --- a/org.eclipse.winery.edmm/src/test/java/org/eclipse/winery/edmm/EdmmUtilsTest.java +++ b/org.eclipse.winery.edmm/src/test/java/org/eclipse/winery/edmm/EdmmUtilsTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2020 Contributors to the Eclipse Foundation + * Copyright (c) 2020-2021 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/org.eclipse.winery.edmm/src/test/java/org/eclipse/winery/edmm/JsonBasedEdmmManagerTest.java b/org.eclipse.winery.edmm/src/test/java/org/eclipse/winery/edmm/JsonBasedEdmmManagerTest.java index 271aca8b1c..dd0041b66b 100644 --- a/org.eclipse.winery.edmm/src/test/java/org/eclipse/winery/edmm/JsonBasedEdmmManagerTest.java +++ b/org.eclipse.winery.edmm/src/test/java/org/eclipse/winery/edmm/JsonBasedEdmmManagerTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019-2020 Contributors to the Eclipse Foundation + * Copyright (c) 2019-2021 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -11,7 +11,6 @@ * * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 *******************************************************************************/ - package org.eclipse.winery.edmm; import java.io.File; diff --git a/org.eclipse.winery.repository/src/test/resources/edmmMapping.json b/org.eclipse.winery.edmm/src/test/resources/edmmMapping.json similarity index 100% rename from org.eclipse.winery.repository/src/test/resources/edmmMapping.json rename to org.eclipse.winery.edmm/src/test/resources/edmmMapping.json diff --git a/org.eclipse.winery.frontends/app/topologymodeler/src/app/canvas/canvas.component.ts b/org.eclipse.winery.frontends/app/topologymodeler/src/app/canvas/canvas.component.ts index 05844b0f6e..1522aa0819 100644 --- a/org.eclipse.winery.frontends/app/topologymodeler/src/app/canvas/canvas.component.ts +++ b/org.eclipse.winery.frontends/app/topologymodeler/src/app/canvas/canvas.component.ts @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2017-2020 Contributors to the Eclipse Foundation + * Copyright (c) 2017-2021 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -52,6 +52,7 @@ import { ThreatCreation } from '../models/threatCreation'; import { TopologyTemplateUtil } from '../models/topologyTemplateUtil'; import { ReqCapRelationshipService } from '../services/req-cap-relationship.service'; import { TPolicy } from '../models/policiesModalData'; +import { ManageTopologyService } from '../services/manage-topology.service'; import { WineryRepositoryConfigurationService } from '../../../../tosca-management/src/app/wineryFeatureToggleModule/WineryRepositoryConfiguration.service'; import { RequirementDefinitionModel } from '../models/requirementDefinitonModel'; import { CapabilityDefinitionModel } from '../models/capabilityDefinitionModel'; @@ -187,7 +188,9 @@ export class CanvasComponent implements OnInit, OnDestroy, OnChanges, AfterViewI private policyService: PolicyService, private reqCapRelationshipService: ReqCapRelationshipService, private notify: ToastrService, + private generateTopologyService: ManageTopologyService, private configuration: WineryRepositoryConfigurationService) { + this.newJsPlumbInstance = this.jsPlumbService.getJsPlumbInstance(); this.newJsPlumbInstance.setContainer('container'); @@ -1658,6 +1661,8 @@ export class CanvasComponent implements OnInit, OnDestroy, OnChanges, AfterViewI this.policyService.policyEventListener().subscribe(data => this.toggleModalHandler(data)); this.reqCapRelationshipService.sourceSelectedEvent.subscribe(source => this.setSource(source)); this.reqCapRelationshipService.sendSelectedRelationshipTypeEvent.subscribe(relationship => this.setSelectedRelationshipType(relationship)); + + this.generateTopologyService.subscribeCanvas(this); } /** @@ -2131,29 +2136,7 @@ export class CanvasComponent implements OnInit, OnDestroy, OnChanges, AfterViewI const currentTypeValid = this.entityTypes.relationshipTypes.some(relType => relType.qName === this.selectedRelationshipType.qName); const currentSourceIdValid = this.allNodeTemplates.some(node => node.id === sourceElement); if (sourceElement && currentTypeValid && currentSourceIdValid) { - const prefix = this.backendService.configuration.relationshipPrefix; - const relName = this.selectedRelationshipType.name; - let relNumber = 0; - let relationshipId: string; - - do { - relationshipId = prefix + '_' + relName + '_' + relNumber++; - } while (this.allRelationshipTemplates.find(value => value.id === relationshipId)); - - if (sourceElement !== info.targetId) { - const newRelationship = new TRelationshipTemplate( - { ref: sourceElement }, - { ref: info.targetId }, - this.selectedRelationshipType.name, - relationshipId, - this.selectedRelationshipType.qName, - InheritanceUtils.getDefaultPropertiesFromEntityTypes(this.selectedRelationshipType.qName, this.entityTypes.relationshipTypes), - [], - [], - {} - ); - this.ngRedux.dispatch(this.actions.saveRelationship(newRelationship)); - } + this.generateNewRelationship(sourceElement, info.targetId, this.selectedRelationshipType); } this.unbindConnection(); this.revalidateContainer(); @@ -2161,6 +2144,35 @@ export class CanvasComponent implements OnInit, OnDestroy, OnChanges, AfterViewI } } + generateNewRelationship(sourceElement: string, targetId: string, selectedRelationshipType: EntityType): TRelationshipTemplate { + const prefix = this.backendService.configuration.relationshipPrefix; + const relName = selectedRelationshipType.name; + let relNumber = 0; + let relationshipId: string; + + do { + relationshipId = prefix + '_' + relName + '_' + relNumber++; + } while (this.allRelationshipTemplates.find(value => value.id === relationshipId)); + + if (sourceElement !== targetId) { + const newRelationship = new TRelationshipTemplate( + { ref: sourceElement }, + { ref: targetId }, + selectedRelationshipType.name, + relationshipId, + selectedRelationshipType.qName, + InheritanceUtils.getDefaultPropertiesFromEntityTypes(selectedRelationshipType.name, this.entityTypes.relationshipTypes), + [], + [], + {} + ); + this.ngRedux.dispatch(this.actions.saveRelationship(newRelationship)); + + return newRelationship; + } + return null; + } + bindReqCapConnection() { if (this.jsPlumbBindConnection === false && this.selectedRelationshipType) { this.newJsPlumbInstance.bind('connection', info => { diff --git a/org.eclipse.winery.frontends/app/topologymodeler/src/app/edmmTransformationCheck/edmm-replacement-rules/edmm-replacement-rules.component.html b/org.eclipse.winery.frontends/app/topologymodeler/src/app/edmmTransformationCheck/edmm-replacement-rules/edmm-replacement-rules.component.html new file mode 100644 index 0000000000..43bb3f61fd --- /dev/null +++ b/org.eclipse.winery.frontends/app/topologymodeler/src/app/edmmTransformationCheck/edmm-replacement-rules/edmm-replacement-rules.component.html @@ -0,0 +1,28 @@ + + diff --git a/org.eclipse.winery.frontends/app/topologymodeler/src/app/edmmTransformationCheck/edmm-replacement-rules/edmm-replacement-rules.component.ts b/org.eclipse.winery.frontends/app/topologymodeler/src/app/edmmTransformationCheck/edmm-replacement-rules/edmm-replacement-rules.component.ts new file mode 100644 index 0000000000..634b537404 --- /dev/null +++ b/org.eclipse.winery.frontends/app/topologymodeler/src/app/edmmTransformationCheck/edmm-replacement-rules/edmm-replacement-rules.component.ts @@ -0,0 +1,214 @@ +/******************************************************************************** + * Copyright (c) 2021 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Apache Software License 2.0 + * which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 + ********************************************************************************/ +import { Component, Input, OnInit } from '@angular/core'; +import { EdmmTechnologyTransformationCheck, EdmmTransformationCheckService } from '../edmmTransformationCheck.service'; +import { NgRedux } from '@angular-redux/store'; +import { IWineryState } from '../../redux/store/winery.store'; +import { TNodeTemplate, TTopologyTemplate } from '../../models/ttopology-template'; +import { TopologyRendererActions } from '../../redux/actions/topologyRenderer.actions'; +import { ManageTopologyService } from '../../services/manage-topology.service'; +import { BackendService } from '../../services/backend.service'; + +@Component({ + selector: 'winery-edmm-replacement-rules', + templateUrl: './edmm-replacement-rules.component.html', + styleUrls: [ + '../edmmTransformationCheck.component.css', + '../../navbar/navbar.component.css' + ], + providers: [ + EdmmTransformationCheckService + ] +}) +export class EdmmReplacementRulesComponent implements OnInit { + + pluginName: string; + components: string[]; + toTopology: string; + + private ruleIndex = 0; + + @Input() pluginResult: EdmmTechnologyTransformationCheck; + @Input() currentCandidate: string; + @Input() topologyTemplate: TTopologyTemplate; + @Input() oneToOneMap: Map; + + constructor(private ngRedux: NgRedux, + private actions: TopologyRendererActions, + private manageTopologyService: ManageTopologyService, + private service: EdmmTransformationCheckService, + private backendService: BackendService) { + } + + ngOnInit(): void { + + if (this.pluginResult.replacementRules.length > 0) { + this.pluginName = this.pluginResult.name; + this.updateRule(); + } + } + + private updateRule() { + this.components = this.pluginResult.replacementRules[this.ruleIndex].unsupportedComponents; + this.toTopology = this.parseTopology(this.pluginResult.replacementRules[this.ruleIndex].toTopology); + } + + /** + * @param topology the fromTopology or toTopology contained in the replacementRules + * @param processComponent a function to process each component + * @param processRelation a function to process each relation + * @param obj an object that is passed to every function and then returned + */ + private static navigateTopology( + topology: Map, + processComponent: (component: string, topology: Map, result?: any) => any, + processRelation: (source: string, target: string, relation: string, topology: Map, result?: any) => any, + obj?: any, + ): any { + for (const component in topology) { + if (topology.hasOwnProperty(component)) { + + obj = processComponent(component, topology, obj); + + for (const i in topology[component]['relations']) { + if (topology[component]['relations'].hasOwnProperty(i)) { + for (const relation in topology[component]['relations'][i]) { + if (topology[component]['relations'][i].hasOwnProperty(relation)) { + + obj = processRelation(component, topology[component]['relations'][i][relation], relation, topology, obj); + } + } + } + } + } + } + return obj; + } + + /** + * At the moment the topology represented with a Map is displayed in a yaml-like way to the user. + */ + private parseTopology(topology: Map): string { + return EdmmReplacementRulesComponent.navigateTopology( + topology, + (component, _topology, result) => { + result += component + '\n'; + result += ' type : ' + this.oneToOneMap[_topology[component]['type']] + '\n'; + return result; + }, + (source, target, relation, _topology, result) => { + result += ' - ' + this.oneToOneMap[relation] + ' : ' + target + '\n'; + return result; + }, + '' + ); + } + + applyRule() { + // the center point of the nodes to be deleted will be the starting point to draw new nodes + let x = 0; + let y = 0; + const unsupportedComponents = this.pluginResult.replacementRules[this.ruleIndex].unsupportedComponents; + for (const node of this.topologyTemplate.nodeTemplates) { + for (const componentId of unsupportedComponents) { + if (node.id === componentId) { + x = x + node.x; + y = y + node.y; + // deleting the node + this.manageTopologyService.deleteNode(node.id); + } + } + } + x = x / unsupportedComponents.length; + y = y / unsupportedComponents.length; + + const drawNode = (component: string, topology: Map) => { + // it may be the case that a node has already been created because it was the target of a relation + if (!topology[component].hasOwnProperty('_id')) { + // if the component has not an _id property means that it has not been created + // because it's the first time we meet it + const sourceNode: TNodeTemplate = this.manageTopologyService.newNode(x, y, this.oneToOneMap[topology[component]['type']]); + topology[component]['_id'] = sourceNode.id; + + if (this.oneToOneMap[topology[component]['type']] !== 'Compute') { + // calling backend to create the placeholders scripts + this.service.createPlaceholderScripts(this.oneToOneMap[topology[component]['type']]); + } + } + }; + + EdmmReplacementRulesComponent.navigateTopology( + this.pluginResult.replacementRules[this.ruleIndex].toTopology, + (component, topology) => { + drawNode(component, topology); + }, + (source, target, relation, topology) => { + drawNode(target, topology); + this.manageTopologyService.newRelationship(topology[source]['_id'], topology[target]['_id'], this.oneToOneMap[relation]); + } + ); + + this.backendService.saveTopologyTemplate(this.topologyTemplate).subscribe(); + } + + getColorClass(): string { + const reason = this.pluginResult.replacementRules[this.ruleIndex].reason; + if (reason === 'unsupported') { + return 'notSupported'; + } else if (reason === 'preferred') { + return 'applicable'; + } + return 'partlyApplicable'; + } + + private updateRuleIndex(update: number) { + this.ruleIndex += update; + if (this.ruleIndex > this.pluginResult.replacementRules.length - 1) { + this.ruleIndex = 0; + } else if (this.ruleIndex < 0) { + this.ruleIndex = this.pluginResult.replacementRules.length - 1; + } + } + + nextRule() { + this.moveRule(+1); + } + + prevRule() { + this.moveRule(-1); + } + + private moveRule(update: number) { + this.updateRuleIndex(update); + this.updateRule(); + this.onMouseLeave(); + this.onMouseOver(); + } + + onMouseOver() { + const idList = []; + for (const node of this.topologyTemplate.nodeTemplates) { + for (const componentId of this.pluginResult.replacementRules[this.ruleIndex].unsupportedComponents) { + if (node.id === componentId) { + idList.push(node.id); + } + } + } + this.ngRedux.dispatch(this.actions.highlightNodes(idList)); + } + + onMouseLeave() { + this.ngRedux.dispatch(this.actions.highlightNodes([])); + } +} diff --git a/org.eclipse.winery.frontends/app/topologymodeler/src/app/edmmTransformationCheck/edmmTransformationCheck.component.css b/org.eclipse.winery.frontends/app/topologymodeler/src/app/edmmTransformationCheck/edmmTransformationCheck.component.css index 76df729976..5ee384a376 100644 --- a/org.eclipse.winery.frontends/app/topologymodeler/src/app/edmmTransformationCheck/edmmTransformationCheck.component.css +++ b/org.eclipse.winery.frontends/app/topologymodeler/src/app/edmmTransformationCheck/edmmTransformationCheck.component.css @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2019-2020 Contributors to the Eclipse Foundation + * Copyright (c) 2019-2021 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -23,3 +23,11 @@ .notSupported { background-color: #d43f3a; } + +.cursorpointer{ + cursor: pointer; +} + +.sidebar-root { + float:left; +} diff --git a/org.eclipse.winery.frontends/app/topologymodeler/src/app/edmmTransformationCheck/edmmTransformationCheck.component.html b/org.eclipse.winery.frontends/app/topologymodeler/src/app/edmmTransformationCheck/edmmTransformationCheck.component.html index 1496422b9a..8e21eb23ab 100644 --- a/org.eclipse.winery.frontends/app/topologymodeler/src/app/edmmTransformationCheck/edmmTransformationCheck.component.html +++ b/org.eclipse.winery.frontends/app/topologymodeler/src/app/edmmTransformationCheck/edmmTransformationCheck.component.html @@ -1,5 +1,5 @@ -