summaryrefslogtreecommitdiffstats
path: root/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/JAXBHelper.java
diff options
context:
space:
mode:
Diffstat (limited to 'winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/JAXBHelper.java')
-rw-r--r--winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/JAXBHelper.java374
1 files changed, 374 insertions, 0 deletions
diff --git a/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/JAXBHelper.java b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/JAXBHelper.java
new file mode 100644
index 0000000..84a3e28
--- /dev/null
+++ b/winery/org.eclipse.winery.topologymodeler/src/main/java/org/eclipse/winery/topologymodeler/addons/topologycompleter/helper/JAXBHelper.java
@@ -0,0 +1,374 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Pascal Hirmer.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and the Apache License 2.0 which both accompany this distribution,
+ * and are available at http://www.eclipse.org/legal/epl-v10.html
+ * and http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Contributors:
+ * Pascal Hirmer - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.winery.topologymodeler.addons.topologycompleter.helper;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import org.eclipse.winery.common.ModelUtilities;
+import org.eclipse.winery.common.Util;
+import org.eclipse.winery.model.tosca.Definitions;
+import org.eclipse.winery.model.tosca.TDefinitions;
+import org.eclipse.winery.model.tosca.TEntityTemplate;
+import org.eclipse.winery.model.tosca.TNodeTemplate;
+import org.eclipse.winery.model.tosca.TRelationshipTemplate;
+import org.eclipse.winery.model.tosca.TRelationshipTemplate.SourceElement;
+import org.eclipse.winery.model.tosca.TServiceTemplate;
+import org.eclipse.winery.model.tosca.TTopologyTemplate;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
+/**
+ * This class contains methods for marshalling and unmarshalling a topology XML string via JAXB.
+ *
+ */
+public class JAXBHelper {
+
+ private static final org.slf4j.Logger logger = LoggerFactory.getLogger(JAXBHelper.class.getName());
+
+ /**
+ * This constant is used in the buildXML method which add coordinates to Node Templates so they
+ * are arranged properly in the Winery topology modeler.
+ *
+ * The x coordinate is constant because it is assumed that a stack of NodeTemplates is displayed.
+ */
+ private static final String NODETEMPLATE_X_COORDINATE = "500";
+
+ /**
+ * This method creates an JAXB Unmarshaller used by the methods contained in this class.
+ *
+ * @return the JAXB unmarshaller object
+ *
+ * @throws JAXBException
+ * this exception can occur when the JAXBContext is created
+ */
+ private static Unmarshaller createUnmarshaller() throws JAXBException {
+ // initiate JaxB context
+ JAXBContext context;
+ context = JAXBContext.newInstance(Definitions.class);
+
+ return context.createUnmarshaller();
+ }
+
+ /**
+ * This method returns a {@link TTopologyTemplate} given as XML string as JaxBObject.
+ *
+ * @param xmlString
+ * the {@link TTopologyTemplate} to be unmarshalled
+ *
+ * @return the unmarshalled {@link TTopologyTemplate}
+ */
+ public static TTopologyTemplate getTopologyAsJaxBObject(String xmlString) {
+ try {
+
+ logger.info("Getting Definitions Document...");
+
+ StringReader reader = new StringReader(xmlString);
+
+ // unmarshall the XML string
+ Definitions jaxBDefinitions = (Definitions) createUnmarshaller().unmarshal(reader);
+ TServiceTemplate serviceTemplate = (TServiceTemplate) jaxBDefinitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0);
+
+ logger.info("Unmarshalling successful! ");
+
+ return serviceTemplate.getTopologyTemplate();
+
+ } catch (JAXBException e) {
+ logger.error(e.getLocalizedMessage());
+ }
+ return null;
+ }
+
+ /**
+ * This method returns {@link TRelationshipTemplate}s as a JaxBObject.
+ *
+ * @param xmlString
+ * the {@link TRelationshipTemplate} to be unmarshalled
+ *
+ * @return the unmarshalled {@link TRelationshipTemplate}
+ */
+ public static List<TRelationshipTemplate> getRelationshipTemplatesAsJaxBObject(String xmlString) {
+ try {
+ StringReader reader = new StringReader(xmlString);
+
+ // unmarshall
+ Definitions jaxBDefinitions = (Definitions) createUnmarshaller().unmarshal(reader);
+ TServiceTemplate serviceTemplate = (TServiceTemplate) jaxBDefinitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0);
+
+ List<TRelationshipTemplate> foundRTs = new ArrayList<>();
+ for (TEntityTemplate entity : serviceTemplate.getTopologyTemplate().getNodeTemplateOrRelationshipTemplate()) {
+ if (entity instanceof TRelationshipTemplate) {
+ foundRTs.add((TRelationshipTemplate) entity);
+ }
+ }
+
+ return foundRTs;
+
+ } catch (JAXBException e) {
+ logger.error(e.getLocalizedMessage());
+ }
+ return null;
+
+ }
+
+ /**
+ * Turns XML Strings into {@link TEntityTemplate} objects using JaxB.
+ *
+ * @param xmlString
+ * the XMLString to be parsed
+ * @return the parsed XMLString as {@link TEntityTemplate}
+ */
+ public static List<TEntityTemplate> getEntityTemplatesAsJaxBObject(String xmlString) {
+ try {
+ StringReader reader = new StringReader(xmlString);
+
+ Definitions jaxBDefinitions = (Definitions) createUnmarshaller().unmarshal(reader);
+ TServiceTemplate serviceTemplate = (TServiceTemplate) jaxBDefinitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0);
+
+ return serviceTemplate.getTopologyTemplate().getNodeTemplateOrRelationshipTemplate();
+
+ } catch (JAXBException e) {
+ logger.error(e.getLocalizedMessage());
+ }
+ return null;
+
+ }
+
+ /**
+ * Converts any object of the TOSCA data model to a JaxBObject.
+ *
+ * @param xmlString
+ * the {@link Definitions} object to be converted
+ *
+ * @return the unmarshalled {@link Definitions} object
+ */
+ public static Definitions getXasJaxBObject(String xmlString) {
+ try {
+ StringReader reader = new StringReader(xmlString);
+ Definitions jaxBDefinitions = (Definitions) createUnmarshaller().unmarshal(reader);
+
+ return jaxBDefinitions;
+
+ } catch (JAXBException e) {
+ logger.error(e.getLocalizedMessage());
+ }
+ return null;
+
+ }
+
+ /**
+ * This method adds a selection of {@link TNodeTemplate}- and {@link TRelationshipTemplate}-XML-Strings to a {@link TTopologyTemplate}-XML-String using JAXB.
+ * After the templates have been added, the {@link TTopologyTemplate} object is re-marshalled to an XML-String.
+ *
+ * This method is called by the selectionHandler.jsp after several Node or RelationshipTemplates have been chosen in a dialog.
+ *
+ * @param topology
+ * the topology as XML string
+ * @param allTemplateChoicesAsXML
+ * all possible template choices as TOSCA-XML strings containing the complete templates
+ * @param selectedNodeTemplatesAsJSON
+ * the names of the selected NodeTemplates as JSONArray
+ * @param selectedRelationshipTemplatesAsJSON
+ * the names of the selected RelationshipTemplates as JSONArray
+ *
+ * @return the complete topology XML string
+ */
+ public static String addTemplatesToTopology(String topology, String allTemplateChoicesAsXML, String selectedNodeTemplatesAsJSON, String selectedRelationshipTemplatesAsJSON) {
+ try {
+
+ // initialization code for the jackson types used to convert JSON string arrays to a java.util.List
+ ObjectMapper mapper = new ObjectMapper();
+ TypeFactory factory = mapper.getTypeFactory();
+
+ // convert the JSON array containing the names of the selected RelationshipTemplates to a java.util.List
+ List<String> selectedRelationshipTemplates = mapper.readValue(selectedRelationshipTemplatesAsJSON, factory.constructCollectionType(List.class, String.class));
+
+ // convert the topology and the choices to objects using JAXB
+ TTopologyTemplate topologyTemplate = getTopologyAsJaxBObject(topology);
+ List<TEntityTemplate> allTemplateChoices = getEntityTemplatesAsJaxBObject(allTemplateChoicesAsXML);
+
+ // this distinction of cases is necessary because it is possible that only RelationshipTemplates have been selected
+ if (selectedNodeTemplatesAsJSON != null) {
+
+ // convert the JSON string array containing the names of the selected NodeTemplates to a java.util.List
+ List<String> selectedNodeTemplates = mapper.readValue(selectedNodeTemplatesAsJSON, factory.constructCollectionType(List.class, String.class));
+
+ // search the selected NodeTemplate in the List of all choices by its name to receive its object which will ne added to the topology
+ for (String nodeTemplateName : selectedNodeTemplates) {
+ for (TEntityTemplate choice : allTemplateChoices) {
+ if (choice instanceof TNodeTemplate) {
+ TNodeTemplate nodeTemplate = (TNodeTemplate) choice;
+ // matching a name is usually unsafe because the uniqueness cannot be assured,
+ // however similar names are not possible at this location due to the implementation of the selection dialogs
+ if (nodeTemplateName.equals(nodeTemplate.getName())) {
+ // add the selected NodeTemplate to the topology
+ topologyTemplate.getNodeTemplateOrRelationshipTemplate().add(nodeTemplate);
+
+ // due to the mapping of IDs in the selection dialog, the corresponding Relationship Template of the inserted Node Template misses its SourceElement.
+ // Re-add it to avoid errors.
+ for (TEntityTemplate entity: topologyTemplate.getNodeTemplateOrRelationshipTemplate()) {
+ if (entity instanceof TRelationshipTemplate) {
+ TRelationshipTemplate relationshipTemplate = (TRelationshipTemplate) entity;
+ if (relationshipTemplate.getSourceElement().getRef() == null) {
+ // connect to the added NodeTemplate
+ SourceElement sourceElement = new SourceElement();
+ sourceElement.setRef(nodeTemplate);
+ relationshipTemplate.setSourceElement(sourceElement);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // now search and add the selected RelationshipTemplate object connecting to the inserted NodeTemplate
+ for (String relationshipTemplateName : selectedRelationshipTemplates) {
+ for (TEntityTemplate toBeAdded : allTemplateChoices) {
+ if (toBeAdded instanceof TRelationshipTemplate) {
+ TRelationshipTemplate relationshipTemplate = (TRelationshipTemplate) toBeAdded;
+ if (relationshipTemplateName.equals(relationshipTemplate.getName())) {
+ topologyTemplate.getNodeTemplateOrRelationshipTemplate().add(relationshipTemplate);
+ }
+ }
+ }
+ }
+
+ } else {
+ // in this case only Relationship Templates have been selected
+ List<TRelationshipTemplate> allRelationshipTemplateChoices = JAXBHelper.getRelationshipTemplatesAsJaxBObject(allTemplateChoicesAsXML);
+
+ // add the target Node Template to the topology which is unique due to the implementation of the selection dialog
+ topologyTemplate.getNodeTemplateOrRelationshipTemplate().add((TNodeTemplate) ((TRelationshipTemplate) allRelationshipTemplateChoices.get(0)).getTargetElement().getRef());
+
+ // search the JAXB object of the selected RelationshipTemplate and add it to the topology
+ for (String relationshipTemplateName : selectedRelationshipTemplates) {
+ for (TRelationshipTemplate choice : allRelationshipTemplateChoices) {
+ if (relationshipTemplateName.equals(choice.getName())) {
+ topologyTemplate.getNodeTemplateOrRelationshipTemplate().add(choice);
+ }
+ }
+ }
+
+ for (TEntityTemplate entityTemplate : topologyTemplate.getNodeTemplateOrRelationshipTemplate()) {
+ if (entityTemplate instanceof TRelationshipTemplate) {
+ TRelationshipTemplate relationship = (TRelationshipTemplate) entityTemplate;
+
+ // due to the mapping of IDs in the selection dialog, the corresponding Relationship Template of the inserted Node Template misses its SourceElement.
+ // Re-add it to avoid errors.
+ if (relationship.getSourceElement().getRef() == null) {
+ relationship.getSourceElement().setRef((TNodeTemplate) ((TRelationshipTemplate) allRelationshipTemplateChoices.get(0)).getTargetElement().getRef());
+ }
+ }
+ }
+ }
+
+ // re-convert the topology from a JAXB object to an XML string and return it
+ Definitions definitions = new Definitions();
+ TServiceTemplate st = new TServiceTemplate();
+ st.setTopologyTemplate(topologyTemplate);
+ definitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().add(st);
+ JAXBContext context = JAXBContext.newInstance(Definitions.class);
+ Marshaller m = context.createMarshaller();
+ StringWriter stringWriter = new StringWriter();
+
+ m.marshal(definitions, stringWriter);
+
+ return stringWriter.toString();
+
+ } catch (JAXBException | IOException e) {
+ logger.error(e.getLocalizedMessage());
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Marshalls a JAXB object of the TOSCA model to an XML string.
+ *
+ * @param clazz
+ * the class of the object
+ * @param obj
+ * the object to be marshalled
+ *
+ * @return
+ */
+ public static String getXMLAsString(@SuppressWarnings("rawtypes") Class clazz, Object obj) {
+ try {
+ @SuppressWarnings("rawtypes")
+ JAXBElement rootElement = Util.getJAXBElement(clazz, obj);
+ JAXBContext context = JAXBContext.newInstance(TDefinitions.class);
+ Marshaller m;
+
+ m = context.createMarshaller();
+
+ StringWriter w = new StringWriter();
+ m.marshal(rootElement, w);
+ String res = w.toString();
+
+ return res;
+ } catch (JAXBException e) {
+ logger.error(e.getLocalizedMessage());
+ }
+ return null;
+ }
+
+ /**
+ * This methods alters the XML with JAXB so it can be imported in Winery. This is necessary because Winery needs additional information for the position of the templates in the
+ * Winery-Modeler-UI.
+ *
+ * This code is adapted from the org.eclipse.winery.repository.Utils.getXMLAsString() method.
+ *
+ * @param topology
+ * the {@link TTopologyTemplate} to be altered
+ *
+ * @return the altered {@link TTopologyTemplate}
+ */
+ public static TTopologyTemplate buildXML(TTopologyTemplate topology) {
+
+ // the coordinate of the NodeTemplate in Winery. Begin 100 pixel from the top to improve arrangement.
+ int yCoordinates = 100;
+
+ for (TEntityTemplate template : topology.getNodeTemplateOrRelationshipTemplate()) {
+ // add node templates
+ if (template instanceof TNodeTemplate) {
+
+ TNodeTemplate nodeTemplate = (TNodeTemplate) template;
+
+ // remove the Requirements tag if necessary
+ if (nodeTemplate.getRequirements() != null && nodeTemplate.getRequirements().getRequirement() == null) {
+ nodeTemplate.setRequirements(null);
+ }
+
+ ModelUtilities.setLeft(nodeTemplate, NODETEMPLATE_X_COORDINATE);
+ ModelUtilities.setTop(nodeTemplate, Integer.toString(yCoordinates));
+
+ yCoordinates += 150;
+ }
+ }
+
+ return topology;
+ }
+}