Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Feature/properties in boundary definitions #113

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

Expand Down Expand Up @@ -190,26 +189,11 @@ public List<TPolicy> getPolicy() {
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"any",
"propertyMappings"
})
public static class Properties {
public static class Properties extends TEntityTemplate.Properties {

@XmlAnyElement(lax = true)
protected Object any;
@XmlElement(name = "PropertyMappings")
protected TBoundaryDefinitions.Properties.PropertyMappings propertyMappings;

@Nullable
public Object getAny() {
return any;
}

public void setAny(@Nullable Object value) {
this.any = value;
}

public TBoundaryDefinitions.Properties.@Nullable PropertyMappings getPropertyMappings() {
return propertyMappings;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
Expand All @@ -32,7 +31,6 @@
import org.eclipse.winery.model.tosca.kvproperties.WinerysPropertiesDefinition;
import org.eclipse.winery.model.tosca.visitor.Visitor;

import com.fasterxml.jackson.annotation.JsonIgnore;
import io.github.adr.embedded.ADR;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
Expand All @@ -52,8 +50,7 @@
TPolicyType.class
})
public abstract class TEntityType extends TExtensibleElements implements HasName, HasInheritance, HasTargetNamespace {
public static final String NS_SUFFIX_PROPERTIESDEFINITION_WINERY = "propertiesdefinition/winery";


@XmlElement(name = "Tags")
protected TTags tags;
@XmlElement(name = "DerivedFrom")
Expand Down Expand Up @@ -178,47 +175,19 @@ public void setTargetNamespace(@Nullable String value) {
this.targetNamespace = value;
}

/**
* This is a special method for Winery. Winery allows to define a property definition by specifying name/type
* values. Instead of parsing the extensible elements returned TDefinitions, this method is a convenience method to
* access this information
*
* @return a WinerysPropertiesDefinition object, which includes a map of name/type-pairs denoting the associated
* property definitions. A default element name and namespace is added if it is not defined in the underlying XML.
* null if no Winery specific KV properties are defined for the given entity type
*/
@XmlTransient
@JsonIgnore
public WinerysPropertiesDefinition getWinerysPropertiesDefinition() {
// similar implementation as org.eclipse.winery.repository.resources.entitytypes.properties.PropertiesDefinitionResource.getListFromEntityType(TEntityType)
WinerysPropertiesDefinition res = null;
for (Object o : this.getAny()) {
if (o instanceof WinerysPropertiesDefinition) {
res = (WinerysPropertiesDefinition) o;
}
}

if (res != null) {
// we put defaults if elementname and namespace have not been set

if (res.getElementName() == null) {
res.setElementName("Properties");
}

if (res.getNamespace() == null) {
// we use the targetnamespace of the original element
String ns = this.getTargetNamespace();
if (!ns.endsWith("/")) {
ns += "/";
}
ns += NS_SUFFIX_PROPERTIESDEFINITION_WINERY;
res.setNamespace(ns);
@Override
protected void setWPDNamespace(WinerysPropertiesDefinition res) {
if (res.getNamespace() == null) {
// we use the targetnamespace of the original element
String ns = this.getTargetNamespace();
if (!ns.endsWith("/")) {
ns += "/";
}
ns += NS_SUFFIX_PROPERTIESDEFINITION_WINERY;
res.setNamespace(ns);
}

return res;
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "")
public static class DerivedFrom implements HasType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@
import javax.xml.bind.annotation.XmlAnyAttribute;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import javax.xml.namespace.QName;

import org.eclipse.winery.model.tosca.kvproperties.WinerysPropertiesDefinition;
import org.eclipse.winery.model.tosca.visitor.Visitor;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.github.adr.embedded.ADR;
import org.eclipse.jdt.annotation.NonNull;
Expand Down Expand Up @@ -60,6 +63,7 @@
})
@JsonInclude(JsonInclude.Include.NON_NULL)
public abstract class TExtensibleElements {
public static final String NS_SUFFIX_PROPERTIESDEFINITION_WINERY = "propertiesdefinition/winery";

protected List<TDocumentation> documentation;

Expand All @@ -68,7 +72,7 @@ public abstract class TExtensibleElements {

@XmlAnyAttribute
@NonNull
private Map<QName, String> otherAttributes = new HashMap<QName, String>();
private Map<QName, String> otherAttributes = new HashMap<>();

public TExtensibleElements() {
}
Expand Down Expand Up @@ -101,19 +105,59 @@ public int hashCode() {
@NonNull
public List<TDocumentation> getDocumentation() {
if (documentation == null) {
documentation = new ArrayList<TDocumentation>();
documentation = new ArrayList<>();
}
return this.documentation;
}

@NonNull
public List<Object> getAny() {
if (any == null) {
any = new ArrayList<Object>();
any = new ArrayList<>();
}
return this.any;
}

/**
* This is a special method for Winery. Winery allows to define a property definition by specifying name/type
* values. Instead of parsing the extensible elements returned TDefinitions, this method is a convenience method to
* access this information
*
* @return a WinerysPropertiesDefinition object, which includes a map of name/type-pairs denoting the associated
* property definitions. A default element name and namespace is added if it is not defined in the underlying XML.
* null if no Winery specific KV properties are defined for the given entity type
*/
@XmlTransient
@JsonIgnore
public WinerysPropertiesDefinition getWinerysPropertiesDefinition() {
// similar implementation as org.eclipse.winery.repository.resources.entitytypes.properties.PropertiesDefinitionResource.getListFromEntityType(TEntityType)
WinerysPropertiesDefinition res = null;
for (Object o : this.getAny()) {
if (o instanceof WinerysPropertiesDefinition) {
res = (WinerysPropertiesDefinition) o;
}
}

if (res != null) {
// we put defaults if elementname and namespace have not been set
setWPDElement(res);
setWPDNamespace(res);
}

return res;
}

protected void setWPDElement(WinerysPropertiesDefinition res) {
if (res.getElementName() == null) {
res.setElementName("Properties");
}
}

protected void setWPDNamespace(WinerysPropertiesDefinition res) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could actually implement it on this level since the methods are identical. To be able to use the getTargetNamespace method, you can check if the current object is an instance of HasTargetNamespace and cast it. Otherwise, you could use a default namespace.

// bo be overridden by subclasses willing to use getWinerysPropertiesDefinition()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be marked as abstract then, to force said overriding? This class is already abstract so we're not giving up anything for that

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not sure if all TExtensibleElements actually need WPD support, since initially only TEntityType supported them. This is an attempt to reuse the method in both TEntityTypes and TServiceTemplates without duplicating it and at the same time without putting additional requirements on TExtensibleElements.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need to have this "abstract" method. The implementations in both are similar and you could check if the current class is an instance of HasTargetNamespace, and otherwise use a default one

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, that's a good solution if a namespace has to be set in the same way for both TEntityType and TServiceTemplate (currently setWPDNamespace is identical, so I assume there's no need for different implementations)

// Template method pattern
}

@NonNull
public Map<QName, String> getOtherAttributes() {
return otherAttributes;
Expand Down Expand Up @@ -254,6 +298,5 @@ public T addOtherAttributes(QName key, String value) {

@ADR(11)
public abstract T self();

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,25 @@
import javax.xml.bind.annotation.XmlType;
import javax.xml.namespace.QName;

import org.eclipse.winery.model.tosca.constants.Namespaces;
import org.eclipse.winery.model.tosca.kvproperties.WinerysPropertiesDefinition;
import org.eclipse.winery.model.tosca.utils.RemoveEmptyLists;
import org.eclipse.winery.model.tosca.visitor.Visitor;

import org.eclipse.jdt.annotation.Nullable;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "tServiceTemplate", propOrder = {
"propertiesDefinition",
"tags",
"boundaryDefinitions",
"topologyTemplate",
"plans"
})
public class TServiceTemplate extends HasId implements HasName, HasTargetNamespace {

@XmlElement(name = "BoundaryDefPropertiesDefinition", namespace = Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE)
protected TServiceTemplate.PropertiesDefinition propertiesDefinition;

@XmlElement(name = "Tags")
protected TTags tags;
Expand Down Expand Up @@ -66,6 +72,7 @@ public TServiceTemplate() {

public TServiceTemplate(Builder builder) {
super(builder);
this.propertiesDefinition = builder.propertiesDefinition;
this.tags = builder.tags;
this.boundaryDefinitions = builder.boundaryDefinitions;
this.topologyTemplate = builder.topologyTemplate;
Expand All @@ -81,7 +88,8 @@ public boolean equals(Object o) {
if (!(o instanceof TServiceTemplate)) return false;
if (!super.equals(o)) return false;
TServiceTemplate that = (TServiceTemplate) o;
return Objects.equals(tags, that.tags) &&
return Objects.equals(propertiesDefinition, that.propertiesDefinition) &&
Objects.equals(tags, that.tags) &&
Objects.equals(boundaryDefinitions, that.boundaryDefinitions) &&
Objects.equals(topologyTemplate, that.topologyTemplate) &&
Objects.equals(plans, that.plans) &&
Expand All @@ -92,7 +100,7 @@ public boolean equals(Object o) {

@Override
public int hashCode() {
return Objects.hash(super.hashCode(), tags, boundaryDefinitions, topologyTemplate, plans, name, targetNamespace, substitutableNodeType);
return Objects.hash(super.hashCode(), propertiesDefinition, tags, boundaryDefinitions, topologyTemplate, plans, name, targetNamespace, substitutableNodeType);
}

@Nullable
Expand Down Expand Up @@ -169,11 +177,54 @@ public void accept(Visitor visitor) {
visitor.visit(this);
}

public TServiceTemplate.@Nullable PropertiesDefinition getPropertiesDefinition() {
return propertiesDefinition;
}

public void setPropertiesDefinition(TServiceTemplate.@Nullable PropertiesDefinition value) {
this.propertiesDefinition = value;
}

/**
* <p>Java class for anonymous complex type.
* <p>
* <p>The following schema fragment specifies the expected content contained within this class.
* <p>
* <pre>
* &lt;complexType>
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;attribute name="element" type="{http://www.w3.org/2001/XMLSchema}QName" />
* &lt;attribute name="type" type="{http://www.w3.org/2001/XMLSchema}QName" />
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "")
public static class PropertiesDefinition extends TEntityType.PropertiesDefinition {
}

@Override
protected void setWPDNamespace(WinerysPropertiesDefinition res) {
if (Objects.isNull(res.getNamespace())) {
// we use the targetnamespace of the original element
String ns = this.getTargetNamespace();
if (!ns.endsWith("/")) {
ns += "/";
}
ns += NS_SUFFIX_PROPERTIESDEFINITION_WINERY;
res.setNamespace(ns);
}
}

public static class Builder extends HasId.Builder<Builder> {
private final TTopologyTemplate topologyTemplate;

private TTags tags;
private TBoundaryDefinitions boundaryDefinitions;
private TServiceTemplate.PropertiesDefinition propertiesDefinition;
private TPlans plans;
private String name;
private String targetNamespace;
Expand Down Expand Up @@ -255,5 +306,10 @@ public Builder self() {
public TServiceTemplate build() {
return new TServiceTemplate(this);
}

public Builder setPropertiesDefinition(PropertiesDefinition propertiesDefinition) {
this.propertiesDefinition = propertiesDefinition;
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ public static Document getWinerysPropertiesDefinitionXsdAsDocument(WinerysProper
* Removes an existing Winery's Properties definition. If no such definition exists, the TEntityType is not
* modified
*/
public static void removeWinerysPropertiesDefinition(TEntityType et) {
public static void removeWinerysPropertiesDefinition(TExtensibleElements et) {
for (Iterator<Object> iterator = et.getAny().iterator(); iterator.hasNext(); ) {
Object o = iterator.next();
if (o instanceof WinerysPropertiesDefinition) {
Expand All @@ -156,7 +156,7 @@ public static void removeWinerysPropertiesDefinition(TEntityType et) {
}
}

public static void replaceWinerysPropertiesDefinition(TEntityType et, WinerysPropertiesDefinition wpd) {
public static void replaceWinerysPropertiesDefinition(TExtensibleElements et, WinerysPropertiesDefinition wpd) {
ModelUtilities.removeWinerysPropertiesDefinition(et);
et.getAny().add(wpd);
}
Expand Down
Loading