3838public class ToscaParser {
3939 private final Logger logger = LogManager .getLogger (ToscaParser .class );
4040
41- private enum FieldDefinitionType {
41+ protected enum TypeOfToscaField {
4242 ATTRIBUTE , PROPERTY
4343 }
4444
45- private static final String NODE_TYPES_KEY = "node_types" ;
4645 private static final String DATA_TYPES_KEY = "data_types" ;
46+ private static final String NODE_TYPES_KEY = "node_types" ;
4747
48- private static final String NODE_TYPES_PROPERTIES_KEY = "properties" ;
4948 private static final String NODE_TYPES_ATTRIBUTES_KEY = "attributes" ;
49+ private static final String NODE_TYPES_PROPERTIES_KEY = "properties" ;
5050
51- private static final String FIELDS_DESCRIPTION_KEY = "description" ;
5251 private static final String FIELDS_TYPE_KEY = "type" ;
53- private static final String FIELDS_VALIDATION_KEY = "validation" ;
5452 private static final String FIELDS_REQUIRED_KEY = "required" ;
53+ private static final String FIELDS_VALIDATION_KEY = "validation" ;
54+ private static final String FIELDS_DESCRIPTION_KEY = "description" ;
5555 private static final String FIELDS_ENTRY_SCHEMA_KEY = "entry_schema" ;
5656
57+ /**
58+ * Parses a node type definition file.
59+ * @param nodeTypeContent The YAML content of the node type definition file.
60+ * @return a {@link ToscaNodeType} representing the node type.
61+ */
5762 public ToscaNodeType parseNodeTypeDefinitionFile (String nodeTypeContent ) {
5863 Object rawYaml = ToscaYamlHelper .loadYaml (nodeTypeContent );
5964 Map <String , Object > yamlRoot = ToscaYamlHelper .asMap (rawYaml );
6065 Map <String , ToscaDataTypeDefinition > dataTypes = parseDataTypes (yamlRoot );
6166 return parseNodeType (yamlRoot , dataTypes );
6267 }
6368
69+ /**
70+ * Parses all data types defined in the TOSCA file.
71+ * @param yamlRoot The root of the YAML file.
72+ * @return a map of {@link ToscaDataTypeDefinition} representing the data types, whose key is the name of the data type and whose value is the data type itself.
73+ */
6474 protected Map <String , ToscaDataTypeDefinition > parseDataTypes (Map <String , Object > yamlRoot ) {
6575 Map <String , Object > dataTypesRaw = ToscaYamlHelper .asMap (yamlRoot .get (DATA_TYPES_KEY ));
6676 logger .info ("Parsing the following data types: {}." , dataTypesRaw ::keySet );
6777 return dataTypesRaw .entrySet ().stream ().map (dataTypeEntry -> {
6878 String dataTypeName = dataTypeEntry .getKey ();
6979 Map <String , Object > dataTypeBody = ToscaYamlHelper .asMap (dataTypeEntry .getValue ());
70- Map <String , ToscaPropertyDefinition > propertyDefinitions = (Map <String , ToscaPropertyDefinition >) parseFieldDefinition (dataTypeBody .get (NODE_TYPES_PROPERTIES_KEY ), FieldDefinitionType .PROPERTY , null );
80+ Map <String , ToscaPropertyDefinition > propertyDefinitions = (Map <String , ToscaPropertyDefinition >) parseField (dataTypeBody .get (NODE_TYPES_PROPERTIES_KEY ), TypeOfToscaField .PROPERTY , null );
7181 return new ToscaDataTypeDefinition (dataTypeName , propertyDefinitions );
7282 }).collect (Collectors .toMap (ToscaDataTypeDefinition ::getName , (dataType ) -> dataType ));
7383 }
7484
75- private ToscaNodeType parseNodeType (Map <String , Object > yamlRoot , Map <String , ToscaDataTypeDefinition > dataTypes ) {
85+ /**
86+ * Parses a node type definition.
87+ * @param yamlRoot The root of the YAML node type definition file.
88+ * @param dataTypes Available data types.
89+ * @return a {@link ToscaNodeType} representing the node type.
90+ */
91+ protected ToscaNodeType parseNodeType (Map <String , Object > yamlRoot , Map <String , ToscaDataTypeDefinition > dataTypes ) {
7692 Map .Entry <String , Object > nodeTypeRaw = ToscaYamlHelper .asMap (yamlRoot .get (NODE_TYPES_KEY )).entrySet ().iterator ().next ();
7793 String nodeTypeName = nodeTypeRaw .getKey ();
7894 logger .info ("Parsing the following node type: [{}]." , nodeTypeName );
7995 Map <String , Object > nodeTypeBody = ToscaYamlHelper .asMap (nodeTypeRaw .getValue ());
80- Map <String , ToscaPropertyDefinition > propertyDefinitions = (Map <String , ToscaPropertyDefinition >) parseFieldDefinition (nodeTypeBody .get (NODE_TYPES_PROPERTIES_KEY ), FieldDefinitionType .PROPERTY , dataTypes );
81- Map <String , ToscaAttributeDefinition > attributeDefinitions = (Map <String , ToscaAttributeDefinition >) parseFieldDefinition (nodeTypeBody .get (NODE_TYPES_ATTRIBUTES_KEY ), FieldDefinitionType .ATTRIBUTE , dataTypes );
96+ Map <String , ToscaPropertyDefinition > propertyDefinitions = (Map <String , ToscaPropertyDefinition >) parseField (nodeTypeBody .get (NODE_TYPES_PROPERTIES_KEY ), TypeOfToscaField .PROPERTY , dataTypes );
97+ Map <String , ToscaAttributeDefinition > attributeDefinitions = (Map <String , ToscaAttributeDefinition >) parseField (nodeTypeBody .get (NODE_TYPES_ATTRIBUTES_KEY ), TypeOfToscaField .ATTRIBUTE , dataTypes );
8298 ToscaNodeType nodeType = new ToscaNodeType (nodeTypeName , propertyDefinitions , attributeDefinitions );
8399 logger .info ("Successfully parsed the following node type: [{}]." , nodeType ::toString );
84100 return nodeType ;
85101 }
86102
87- private Map <String , ? extends ToscaFieldDefinition > parseFieldDefinition (Object rawFields , FieldDefinitionType fieldDefinitionType , Map <String , ToscaDataTypeDefinition > dataTypes ) {
103+ /**
104+ * Parses a field (property or attribute) of a TOSCA resource.
105+ * @param rawFields The body of the field. Example: "{ name: { type: string, description: Name } }"
106+ * @param typeOfToscaField The type of the field that will be parsed.
107+ * @param dataTypes Available data types. If null, then the type of the fields must be a primitive or a collection.
108+ * @return a map of {@link ToscaFieldDefinition} representing the fields, whose key is the name of the field and whose value is the field itself.
109+ */
110+ protected Map <String , ? extends ToscaFieldDefinition > parseField (Object rawFields , TypeOfToscaField typeOfToscaField , Map <String , ToscaDataTypeDefinition > dataTypes ) {
88111 Map <String , Object > fields = ToscaYamlHelper .asMap (rawFields );
89112 logger .debug ("Parsing the following {}: {}." ,
90- () -> fieldDefinitionType == FieldDefinitionType .ATTRIBUTE ? "attributes" : "properties" , fields ::keySet );
113+ () -> typeOfToscaField == TypeOfToscaField .ATTRIBUTE ? "attributes" : "properties" , fields ::keySet );
91114
92115 return fields .entrySet ().stream ().map ((field ) -> {
93- String fieldName = field .getKey ();
116+ String name = field .getKey ();
94117 Map <String , Object > fieldBody = ToscaYamlHelper .asMap (field .getValue ());
95- String fieldDescription = ToscaYamlHelper .asString (fieldBody .get (FIELDS_DESCRIPTION_KEY ));
96- ToscaTypeDefinition fieldType = parseFieldType (fieldBody , dataTypes );
118+ String description = ToscaYamlHelper .asString (fieldBody .get (FIELDS_DESCRIPTION_KEY ));
119+ ToscaTypeDefinition type = parseType (fieldBody , dataTypes );
97120
98- if (fieldDefinitionType == FieldDefinitionType .ATTRIBUTE ) {
99- ToscaAttributeDefinition attributeDefinition = new ToscaAttributeDefinition (fieldName , fieldDescription , fieldType );
121+ if (typeOfToscaField == TypeOfToscaField .ATTRIBUTE ) {
122+ ToscaAttributeDefinition attributeDefinition = new ToscaAttributeDefinition (name , description , type );
100123 logger .debug ("Successfully parsed the following attribute: [{}]." , attributeDefinition ::toString );
101124 return attributeDefinition ;
102125 }
103126
104127 boolean required = ToscaYamlHelper .asBoolean (fieldBody .get (FIELDS_REQUIRED_KEY ));
105128 ToscaFunction .ToscaBooleanFunction validation = parseToscaBooleanFunction (ToscaYamlHelper .asMap (fieldBody .get (FIELDS_VALIDATION_KEY )));
106- ToscaPropertyDefinition propertyDefinition = new ToscaPropertyDefinition (fieldName , fieldDescription , fieldType , required , validation );
129+ ToscaPropertyDefinition propertyDefinition = new ToscaPropertyDefinition (name , description , type , required , validation );
107130 logger .debug ("Successfully parsed the following property: [{}]." , propertyDefinition ::toString );
108131 return propertyDefinition ;
109132 }).collect (Collectors .toMap (ToscaFieldDefinition ::getName , (field ) -> field ));
110133 }
111134
112- protected ToscaTypeDefinition parseFieldType (Map <String , Object > fieldBody , Map <String , ToscaDataTypeDefinition > dataTypes ) {
113- String rawType = ToscaYamlHelper .asString (fieldBody .get (FIELDS_TYPE_KEY ));
135+ /**
136+ * Parses the type of TOSCA resource. Types can be primitive, collection, or data type, and are represented by the {@link ToscaTypeDefinition} class.
137+ * @param typeBody The body of the type. Example: "{ type: list, entry_schema: { type: NodeOffering } }"
138+ * @param dataTypes The available data types. If null, then the type being parsed must be either a primitive or a collection.
139+ * @return a {@link ToscaTypeDefinition} representing the type of the field. Null if the type is not recognized.
140+ */
141+ protected ToscaTypeDefinition parseType (Map <String , Object > typeBody , Map <String , ToscaDataTypeDefinition > dataTypes ) {
142+ String rawType = ToscaYamlHelper .asString (typeBody .get (FIELDS_TYPE_KEY ));
114143 logger .debug ("Parsing the following type: [{}]." , rawType );
115144 ToscaPrimitiveType primitiveType = EnumUtils .getEnumIgnoreCase (ToscaPrimitiveType .class , rawType );
116145 if (primitiveType != null ) {
@@ -121,32 +150,47 @@ protected ToscaTypeDefinition parseFieldType(Map<String, Object> fieldBody, Map<
121150 ToscaCollectionType collectionType = EnumUtils .getEnumIgnoreCase (ToscaCollectionType .class , rawType );
122151 if (collectionType != null ) {
123152 logger .debug ("The type is a collection, returning its corresponding ToscaTypeDefinition." );
124- return ToscaTypeDefinition .ofCollection (collectionType , parseFieldType (ToscaYamlHelper .asMap (fieldBody .get (FIELDS_ENTRY_SCHEMA_KEY )), dataTypes ));
153+ return ToscaTypeDefinition .ofCollection (collectionType , parseType (ToscaYamlHelper .asMap (typeBody .get (FIELDS_ENTRY_SCHEMA_KEY )), dataTypes ));
154+ }
155+
156+ if (MapUtils .isEmpty (dataTypes ) || !dataTypes .containsKey (rawType )) {
157+ logger .debug ("The [{}] type is not recognized, returning null." , rawType );
158+ return null ;
125159 }
126160
127161 logger .debug ("The type is a data type, returning its corresponding ToscaTypeDefinition based in the declared data types: {}." , dataTypes ::keySet );
128162 return ToscaTypeDefinition .ofDataType (dataTypes .get (rawType ));
129163 }
130164
165+ /**
166+ * Parses a TOSCA boolean ({@link ToscaFunction.ToscaBooleanFunction}) function.
167+ * @param validationBody The body of the validation field. Example: "{ $valid_values: [ $value, [ CloudManaged, ExternalManaged ] ] }")
168+ * @return a {@link ToscaFunction.ToscaBooleanFunction} representing the boolean function. If the function is not recognized, returns null.
169+ */
131170 protected ToscaFunction .ToscaBooleanFunction parseToscaBooleanFunction (Map <String , Object > validationBody ) {
132171 if (MapUtils .isEmpty (validationBody )) {
133172 return null ;
134173 }
135174
136175 Map .Entry <String , Object > function = validationBody .entrySet ().iterator ().next ();
137176 String name = function .getKey ();
138- Object body = function .getValue ();
177+ Object arguments = function .getValue ();
139178 logger .debug ("Parsing the following TOSCA boolean function: [{}]." , name );
140179 switch (name ) {
141180 case "$valid_values" :
142- return parseValidValuesFunction (body );
181+ return parseValidValuesFunction (arguments );
143182 }
144183 return null ;
145184 }
146185
147- private ToscaFunction .ToscaBooleanFunction parseValidValuesFunction (Object functionBody ) {
148- List <Object > arguments = (List <Object >) functionBody ;
149- List <Object > validValues = (List <Object >) arguments .get (1 );
186+ /**
187+ * Parses the $valid_values TOSCA function.
188+ * @param arguments The arguments of the $valid_values function. Example: "{ $valid_values: [ $value, [ CloudManaged, ExternalManaged ] ] }"
189+ * @return a {@link ToscaBooleanFunctions.ValidValues} (typed as {@link ToscaFunction.ToscaBooleanFunction}) representing the $valid_values function.
190+ */
191+ private ToscaFunction .ToscaBooleanFunction parseValidValuesFunction (Object arguments ) {
192+ List <Object > args = (List <Object >) arguments ;
193+ List <Object > validValues = (List <Object >) args .get (1 );
150194 return new ToscaBooleanFunctions .ValidValues (validValues );
151195 }
152196}
0 commit comments