TOSCA Elements
Whenever the term TOSCA Element
is mentioned, it refers to one of the classes which are used to model TOSCA types, e.g., WebServer
, ContainerCapability
, Requirement
or HostedOn
.
TOSCA Elements are only wrappers
When interacting with a TOSCA element, e.g. with an instance of the MysqlDatabase
class, it seems its implemented like a plain POJO class:
String dbName = node.getDatabaseName();
node.setDatabaseName("my-db");
However, this appearance is deceiving.
The actual implementation of most getters / setters of TOSCA elements look like this:
public String getDatabaseName() {
return get(DATABASE_NAME);
}
public Database setDatabaseName(String databaseName) {
set(DATABASE_NAME, databaseName);
return this;
}
Note: You don't have to type these getters / setters by hand. Instead, use these code templates (if you happen to run intellij). The templates will generate getters / setters based on the defined
ToscaKey
fields.
The above used generic get()
and set()
methods are implemented in the BaseToscaElement
class and look like this:
public <T> T get(ToscaKey<T> key) {
return mappingEntity.getValue(key);
}
public <T> void set(ToscaKey<T> key, T value) {
mappingEntity.setValue(key, value);
}
So whats basically happening? Generally speaking, all data access is delegated to its underlying MappingEntity
. Read about the ServiceGraph to understand how this works.
The truth is: TOSCA Element instances are simple and stupid wrappers.
ToscaKeys
As you might have noticed, the generic get()
and set()
methods expect a ToscaKey
instance. As a whole, a ToscaKey
describes all relevant characteristics of a value belonging to the TOSCA element.
As a general rule, every Tosca Element defines its own ToscaKeys, similar to a POJO defining its data fields. This could look like this:
public static ToscaKey<String> DATABASE_NAME = new ToscaKey<>(PROPERTIES, "name").required();
A ToscaKey has following characteristics:
- Type information. Special care has been taken to achieve type-safety even with a generic approach for getters / setters. A
ToscaKey
contains both generic type information and class type information (because generic type information is erased at runtime, this is needed as well). - Name. The name which is used in TOSCA yaml to refer to this element
- required boolean flag which specifies if a value must be present
- predecssor. Another
ToscaKey
which acts as the predecessor of thisToscaKey
. With defining a predecessor it's possible to map the Key to a nested structure. E.g., above defined key has the predecessorPROPERTIES
(which happens to have the name"properties"
) - so it points to a value inproperties.name
. - directives. When needed, special directives can be saved in a
Map<String,Object>
construction. This is currently used for storing information about default units of TOSCA scalar types.
Note:
ToscaKeys
are not declared asfinal
, as this would cause problems in combination with inheritance (which is used heavily within Tosca Element classes)
RequirementKeys
A RequirementKey
is a special ToscaKey
which allows storage of multiple type information instead of only one.
As the name implies, shall be used for defining TOSCA requirements.
This allows for type-safe handling of its correlated node, capability and relationship.