Skip to content

Commit

Permalink
Purge all References to Types without JAXB-visible namespace URI decl…
Browse files Browse the repository at this point in the history
…aration

This fixes issues in all unit-tests that result in the expected empty prefix not being available
for the TOSCA_NAMESPACE.
  • Loading branch information
Vogel612 committed Aug 4, 2020
1 parent 64ecd8c commit 8d436d0
Show file tree
Hide file tree
Showing 37 changed files with 295 additions and 200 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ private void createPropertiesDefinition(TEntityType toscaType, EntityId typeEnti
EntityId propertiesEntityId = typeEntityId.extend(DefaultKeys.PROPERTIES);
entityGraph.addEntity(new MappingEntity(propertiesEntityId, entityGraph));

toscaType.getWinerysPropertiesDefinition().getPropertyDefinitionKVList().getPropertyDefinitionKVs()
toscaType.getWinerysPropertiesDefinition().getPropertyDefinitions().getPropertyDefinitionKVs()
.forEach(propertyDef -> {
EntityId propertyEntityId = propertiesEntityId.extend(propertyDef.getKey());
entityGraph.addEntity(new MappingEntity(propertyEntityId, entityGraph));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;

Expand All @@ -39,7 +40,7 @@
import org.eclipse.winery.model.tosca.TRelationshipType;
import org.eclipse.winery.model.tosca.TRelationshipTypeImplementation;
import org.eclipse.winery.model.tosca.extensions.kvproperties.PropertyDefinitionKV;
import org.eclipse.winery.model.tosca.extensions.kvproperties.PropertyDefinitionKVList;
import org.eclipse.winery.model.tosca.extensions.kvproperties.PropertyDefinitions;
import org.eclipse.winery.model.tosca.extensions.kvproperties.WinerysPropertiesDefinition;
import org.eclipse.winery.model.tosca.utils.ModelUtilities;

Expand Down Expand Up @@ -84,12 +85,14 @@ void setup() {
TNodeType nodeType3 = new TNodeType();
nodeType3.setName(nodeType3QName.getLocalPart());
nodeType3.setTargetNamespace(nodeType3QName.getNamespaceURI());
PropertyDefinitionKVList kvList = new PropertyDefinitionKVList();
kvList.add(new PropertyDefinitionKV("os_family", "xsd:string"));
kvList.add(new PropertyDefinitionKV("public_key", "xsd:string"));
kvList.add(new PropertyDefinitionKV("ssh_port", "number"));
PropertyDefinitions kvList = new PropertyDefinitions();
kvList.getPropertyDefinitionKVs().addAll(Arrays.asList(
new PropertyDefinitionKV("os_family", "xsd:string"),
new PropertyDefinitionKV("public_key", "xsd:string"),
new PropertyDefinitionKV("ssh_port", "number")
));
WinerysPropertiesDefinition wpd = new WinerysPropertiesDefinition();
wpd.setPropertyDefinitionKVList(kvList);
wpd.setPropertyDefinitions(kvList);
ModelUtilities.replaceWinerysPropertiesDefinition(nodeType3, wpd);
nodeTypes.put(nodeType3QName, nodeType3);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
import org.eclipse.winery.model.tosca.constants.OpenToscaInterfaces;
import org.eclipse.winery.model.tosca.constants.ToscaBaseTypes;
import org.eclipse.winery.model.tosca.extensions.kvproperties.PropertyDefinitionKV;
import org.eclipse.winery.model.tosca.extensions.kvproperties.PropertyDefinitionKVList;
import org.eclipse.winery.model.tosca.extensions.kvproperties.PropertyDefinitions;
import org.eclipse.winery.model.tosca.extensions.kvproperties.WinerysPropertiesDefinition;
import org.eclipse.winery.model.tosca.utils.ModelUtilities;
import org.eclipse.winery.repository.backend.IRepository;
Expand Down Expand Up @@ -276,18 +276,17 @@ public static TTopologyTemplate applyFeaturesForTopology(TTopologyTemplate topol
TNodeType generatedNodeType = createFeatureNodeType(nodeTemplate, featureMap.get(nodeTemplate.getId()));
nodeTemplate.setType(generatedNodeType.getQName());
if (Objects.nonNull(generatedNodeType.getWinerysPropertiesDefinition())) {
PropertyDefinitionKVList definedProperties = generatedNodeType.getWinerysPropertiesDefinition()
.getPropertyDefinitionKVList();
PropertyDefinitions definedProperties = generatedNodeType.getWinerysPropertiesDefinition()
.getPropertyDefinitions();

final @NonNull LinkedHashMap<String, String> kvProperties = ModelUtilities.getPropertiesKV(nodeTemplate) == null
? new LinkedHashMap<>()
: ModelUtilities.getPropertiesKV(nodeTemplate);
if (kvProperties.isEmpty()) {
definedProperties.stream().map(PropertyDefinitionKV::getKey)
definedProperties.getPropertyDefinitionKVs().stream().map(PropertyDefinitionKV::getKey)
.forEach(k -> kvProperties.put(k, ""));
definedProperties.forEach(propertyDefinition -> kvProperties.put(propertyDefinition.getKey(), ""));
} else {
definedProperties.forEach(propertyDefinition -> {
definedProperties.getPropertyDefinitionKVs().forEach(propertyDefinition -> {
if (Objects.isNull(kvProperties.get(propertyDefinition.getKey()))) {
kvProperties.put(propertyDefinition.getKey(), "");
}
Expand Down Expand Up @@ -338,11 +337,11 @@ public static TNodeType createFeatureNodeType(TNodeTemplate nodeTemplate, Map<QN
// prepare Properties
if (Objects.isNull(featureEnrichedNodeType.getWinerysPropertiesDefinition())) {
WinerysPropertiesDefinition props = new WinerysPropertiesDefinition();
props.setPropertyDefinitionKVList(new PropertyDefinitionKVList());
props.setPropertyDefinitions(new PropertyDefinitions());
ModelUtilities.replaceWinerysPropertiesDefinition(featureEnrichedNodeType, props);
}
List<PropertyDefinitionKV> baseProperties = featureEnrichedNodeType.getWinerysPropertiesDefinition()
.getPropertyDefinitionKVList()
.getPropertyDefinitions()
.getPropertyDefinitionKVs();

// prepare Interfaces
Expand Down Expand Up @@ -386,7 +385,8 @@ public static TNodeType createFeatureNodeType(TNodeTemplate nodeTemplate, Map<QN

// merge Properties
if (Objects.nonNull(nodeType.getWinerysPropertiesDefinition())) {
PropertyDefinitionKVList kvList = nodeType.getWinerysPropertiesDefinition().getPropertyDefinitionKVList();
List<PropertyDefinitionKV> kvList = nodeType.getWinerysPropertiesDefinition().getPropertyDefinitions()
.getPropertyDefinitionKVs();
if (Objects.nonNull(kvList) && !kvList.isEmpty()) {
for (PropertyDefinitionKV kv : kvList) {
boolean listContainsProperty = baseProperties.stream()
Expand All @@ -413,8 +413,8 @@ public static TNodeType createFeatureNodeType(TNodeTemplate nodeTemplate, Map<QN
// In the case that neither the basic type, nor the feature types define properties,
// remove them from the type to ensure a compliant XML.
if (Objects.nonNull(featureEnrichedNodeType.getWinerysPropertiesDefinition())
&& Objects.nonNull(featureEnrichedNodeType.getWinerysPropertiesDefinition().getPropertyDefinitionKVList())
&& featureEnrichedNodeType.getWinerysPropertiesDefinition().getPropertyDefinitionKVList().isEmpty()) {
&& Objects.nonNull(featureEnrichedNodeType.getWinerysPropertiesDefinition().getPropertyDefinitions())
&& featureEnrichedNodeType.getWinerysPropertiesDefinition().getPropertyDefinitions().getPropertyDefinitionKVs().isEmpty()) {
ModelUtilities.removeWinerysPropertiesDefinition(featureEnrichedNodeType);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ void mergeFeatureNodeTypeUbuntu() throws Exception {
assertEquals(1, listOfNodeTypes.size() - previousListOfNodeTypes.size());
assertEquals(expectedMergedUbuntuQName, generatedFeatureEnrichedNodeType.getQName());
assertNotNull(generatedFeatureEnrichedNodeType.getWinerysPropertiesDefinition());
assertEquals(9, generatedFeatureEnrichedNodeType.getWinerysPropertiesDefinition().getPropertyDefinitionKVList().size());
assertEquals(9, generatedFeatureEnrichedNodeType.getWinerysPropertiesDefinition().getPropertyDefinitions().getPropertyDefinitionKVs().size());

TNodeTypeImplementation generatedUbuntuImpl = this.repository.getElement(
new ArrayList<>(this.repository.getAllElementsReferencingGivenType(NodeTypeImplementationId.class, expectedMergedUbuntuQName))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Objects;
Expand All @@ -35,7 +36,7 @@
import org.eclipse.winery.model.tosca.TPolicyType;
import org.eclipse.winery.model.tosca.TServiceTemplate;
import org.eclipse.winery.model.tosca.extensions.kvproperties.PropertyDefinitionKV;
import org.eclipse.winery.model.tosca.extensions.kvproperties.PropertyDefinitionKVList;
import org.eclipse.winery.model.tosca.extensions.kvproperties.PropertyDefinitions;
import org.eclipse.winery.model.tosca.extensions.kvproperties.WinerysPropertiesDefinition;
import org.eclipse.winery.model.tosca.utils.ModelUtilities;
import org.eclipse.winery.repository.backend.BackendUtils;
Expand Down Expand Up @@ -289,14 +290,16 @@ public void setupThreatModelingTypes() throws Exception {
threat.setProperties(null);

WinerysPropertiesDefinition threatProps = new WinerysPropertiesDefinition();
PropertyDefinitionKVList threatPropList = new PropertyDefinitionKVList();
PropertyDefinitions threatPropList = new PropertyDefinitions();
threatProps.setElementName("properties");
threatProps.setNamespace(ThreatModelingConstants.THREATMODELING_NAMESPACE.concat("/propertiesdefinition/winery"));

threatPropList.add(new PropertyDefinitionKV(ThreatModelingProperties.description.toString(), "xsd:string"));
threatPropList.add(new PropertyDefinitionKV(ThreatModelingProperties.strideClassification.toString(), "xsd:string"));
threatPropList.add(new PropertyDefinitionKV(ThreatModelingProperties.severity.toString(), "xsd:string"));
threatProps.setPropertyDefinitionKVList(threatPropList);
threatPropList.getPropertyDefinitionKVs().addAll(Arrays.asList(
new PropertyDefinitionKV(ThreatModelingProperties.description.toString(), "xsd:string"),
new PropertyDefinitionKV(ThreatModelingProperties.strideClassification.toString(), "xsd:string"),
new PropertyDefinitionKV(ThreatModelingProperties.severity.toString(), "xsd:string")
));
threatProps.setPropertyDefinitions(threatPropList);

ModelUtilities.replaceWinerysPropertiesDefinition(threat, threatProps);

Expand All @@ -317,12 +320,12 @@ public void setupThreatModelingTypes() throws Exception {
mitigation.setProperties(null);

WinerysPropertiesDefinition mitigationProps = new WinerysPropertiesDefinition();
PropertyDefinitionKVList mitigationPropList = new PropertyDefinitionKVList();
PropertyDefinitions mitigationPropList = new PropertyDefinitions();
mitigationProps.setElementName("properties");
mitigationProps.setNamespace(ThreatModelingConstants.THREATMODELING_NAMESPACE.concat("/propertiesdefinition/winery"));

mitigationPropList.add(new PropertyDefinitionKV(ThreatModelingProperties.ThreatReference.toString(), "xsd:string"));
mitigationProps.setPropertyDefinitionKVList(mitigationPropList);
mitigationPropList.getPropertyDefinitionKVs().add(new PropertyDefinitionKV(ThreatModelingProperties.ThreatReference.toString(), "xsd:string"));
mitigationProps.setPropertyDefinitions(mitigationPropList);

ModelUtilities.replaceWinerysPropertiesDefinition(mitigation, mitigationProps);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
<artifactId>jackson-annotations</artifactId>
<version>2.8.6</version>
</dependency>
<!-- Required to access NamespacePrefixMapper for PropertiesAdapter -->
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.11</version>
</dependency>
<dependency>
<groupId>io.github.adr</groupId>
<artifactId>e-adr</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,9 @@

package org.eclipse.winery.model.jaxbsupport.map;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
Expand All @@ -29,7 +25,8 @@
import org.eclipse.winery.model.converter.support.Namespaces;
import org.eclipse.winery.model.tosca.TEntityTemplate;

import org.eclipse.jdt.annotation.NonNull;
import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
import org.eclipse.jdt.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Comment;
Expand All @@ -39,6 +36,16 @@
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

/**
* <p>
* This XmlAdapter is used to transform between the different {@link TEntityTemplate.Properties} implementations and
* a "raw" xml {@link Element}. Because {@link Element} is an interface, the XmlAdapter declares <tt>Object</tt> as it's
* "intermediate" type.
* <p>
* This use has the additional benefit of removing the explicit LinkedHashMap declarations in both {@link org.eclipse.winery.model.tosca.TEntityTemplate.WineryKVProperties}
* and {@link org.eclipse.winery.model.tosca.TEntityTemplate.YamlProperties} from the JAXBContext, thus avoiding a
* pollution with the namespace URI "" by the use of LinkedHashMap.
*/
public class PropertiesAdapter extends XmlAdapter<Object, TEntityTemplate.Properties> {

private static final Logger LOGGER = LoggerFactory.getLogger(PropertiesAdapter.class);
Expand All @@ -47,8 +54,18 @@ private enum PropertyKind {
XML, YAML, KV
}

@Nullable
private final NamespacePrefixMapper prefixMapper;

public PropertiesAdapter(@Nullable NamespacePrefixMapper prefixMapper) {
this.prefixMapper = prefixMapper;
}

@Override
public TEntityTemplate.Properties unmarshal(Object xmlData) throws Exception {
if (xmlData == null) {
return null;
}
if (!(xmlData instanceof Element)) {
throw new IllegalStateException("Cannot deserialize arbitrary XML if no Element is available. Expected Element, got " + xmlData.getClass().getName());
}
Expand Down Expand Up @@ -111,6 +128,9 @@ private PropertyKind determinePropertyKind(Element element) {

@Override
public Object marshal(TEntityTemplate.Properties jaxb) throws Exception {
if (jaxb == null) {
return null;
}
if (jaxb instanceof TEntityTemplate.WineryKVProperties) {
return marshallWineryKV((TEntityTemplate.WineryKVProperties) jaxb);
}
Expand All @@ -132,16 +152,19 @@ public Object marshal(TEntityTemplate.Properties jaxb) throws Exception {

private Element marshallNestedMap(LinkedHashMap<String, Object> data) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db;
try {
db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
// LOGGER.debug(e.getMessage(), e);
throw new IllegalStateException("Could not instantiate document builder", e);
}
Document doc = db.newDocument();

final String prefix = (prefixMapper != null)
? prefixMapper.getPreferredPrefix(Namespaces.TOSCA_YAML_NS, "", true)
: "";
Element root = doc.createElementNS(Namespaces.TOSCA_YAML_NS, "Properties");
root.setPrefix(prefix);
for (String key : data.keySet()) {
final Object value = data.get(key);
if (value instanceof Map) {
Expand Down Expand Up @@ -173,39 +196,46 @@ private Element marshallNestedMap(Document doc, String elementName, Map<String,
}

private Element marshallWineryKV(TEntityTemplate.WineryKVProperties jaxb) {
TEntityTemplate.WineryKVProperties wkvProps = jaxb;
final String namespace = wkvProps.getNamespace();
String elementName = wkvProps.getElementName();
if (elementName.equals("")) {
elementName = "KVProperties";
final String namespace = jaxb.getNamespace();
String elementName = jaxb.getElementName();
if (elementName == null || elementName.equals("")) {
elementName = "Properties";
}
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db;
try {
db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
// LOGGER.debug(e.getMessage(), e);
throw new IllegalStateException("Could not instantiate document builder", e);
}
Document doc = db.newDocument();
// Because JAXB is unwrapping the top-level element and discarding it, we add this extra wrapper
Element serializationWrapper = doc.createElement("DISCARDED");
doc.appendChild(serializationWrapper);

final String prefix = (prefixMapper != null)
? prefixMapper.getPreferredPrefix(namespace, "", true)
: "";
Element root = doc.createElementNS(namespace, elementName);
doc.appendChild(root);
root.setPrefix(prefix);
serializationWrapper.appendChild(root);

// No wpd - so this is not possible:
// we produce the serialization in the same order the XSD would be generated (because of the usage of xsd:sequence)
// for (PropertyDefinitionKV prop : wpd.getPropertyDefinitionKVList()) {
final LinkedHashMap<String, String> properties = wkvProps.getKVProperties();
final LinkedHashMap<String, String> properties = jaxb.getKVProperties();
for (String key : properties.keySet()) {
Element element = doc.createElementNS(namespace, key);
element.setPrefix(prefix);
root.appendChild(element);
String value = properties.get(key);
if (value != null) {
Text text = doc.createTextNode(value);
element.appendChild(text);
}
}
return root;
return serializationWrapper;
}

public static boolean isKeyValuePropertyDefinition(Element xmlElement) {
Expand Down
Loading

0 comments on commit 8d436d0

Please sign in to comment.