Flexible DSL Types and Templates definition.
[ccsdk/cds.git] / ms / blueprintsprocessor / modules / blueprints / blueprint-core / src / main / kotlin / org / onap / ccsdk / cds / controllerblueprints / core / dsl / BluePrintTemplateDSLBuilder.kt
1 /*
2  *  Copyright © 2019 IBM.
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  */
16
17 package org.onap.ccsdk.cds.controllerblueprints.core.dsl
18
19 import com.fasterxml.jackson.databind.JsonNode
20 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
21 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
22 import org.onap.ccsdk.cds.controllerblueprints.core.data.ArtifactDefinition
23 import org.onap.ccsdk.cds.controllerblueprints.core.data.CapabilityAssignment
24 import org.onap.ccsdk.cds.controllerblueprints.core.data.Implementation
25 import org.onap.ccsdk.cds.controllerblueprints.core.data.InterfaceAssignment
26 import org.onap.ccsdk.cds.controllerblueprints.core.data.NodeTemplate
27 import org.onap.ccsdk.cds.controllerblueprints.core.data.OperationAssignment
28 import org.onap.ccsdk.cds.controllerblueprints.core.data.RelationshipTemplate
29 import org.onap.ccsdk.cds.controllerblueprints.core.data.RequirementAssignment
30 import org.onap.ccsdk.cds.controllerblueprints.core.data.TopologyTemplate
31 import org.onap.ccsdk.cds.controllerblueprints.core.data.Workflow
32 import kotlin.reflect.KClass
33 import kotlin.reflect.KMutableProperty1
34 import kotlin.reflect.full.createInstance
35 import kotlin.reflect.jvm.reflect
36
37 open class TopologyTemplateBuilder {
38     private var topologyTemplate = TopologyTemplate()
39     var nodeTemplates: MutableMap<String, NodeTemplate>? = null
40     var relationshipTemplates: MutableMap<String, RelationshipTemplate>? = null
41     private var workflows: MutableMap<String, Workflow>? = null
42
43     fun nodeTemplate(id: String, type: String, description: String, block: NodeTemplateBuilder.() -> Unit) {
44         if (nodeTemplates == null) nodeTemplates = hashMapOf()
45         nodeTemplates!![id] = NodeTemplateBuilder(id, type, description).apply(block).build()
46     }
47
48     fun nodeTemplate(nodeTemplate: NodeTemplate) {
49         if (nodeTemplates == null) nodeTemplates = hashMapOf()
50         nodeTemplates!![nodeTemplate.id!!] = nodeTemplate
51     }
52
53     fun relationshipTemplate(
54         id: String,
55         type: String,
56         description: String,
57         block: RelationshipTemplateBuilder.() -> Unit
58     ) {
59         if (relationshipTemplates == null) relationshipTemplates = hashMapOf()
60         relationshipTemplates!![id] = RelationshipTemplateBuilder(id, type, description).apply(block).build()
61     }
62
63     fun relationshipTemplate(relationshipTemplate: RelationshipTemplate) {
64         if (relationshipTemplates == null) relationshipTemplates = hashMapOf()
65         relationshipTemplates!![relationshipTemplate.id!!] = relationshipTemplate
66     }
67
68     fun nodeTemplateOperation(
69         nodeTemplateName: String,
70         type: String,
71         interfaceName: String,
72         description: String,
73         operationBlock: OperationAssignmentBuilder<PropertiesAssignmentBuilder,
74             PropertiesAssignmentBuilder>.() -> Unit
75     ) {
76         if (nodeTemplates == null) nodeTemplates = hashMapOf()
77
78         val nodeTemplateBuilder = NodeTemplateBuilder(nodeTemplateName, type, description)
79         nodeTemplateBuilder.operation(interfaceName, "$description operation", operationBlock)
80         nodeTemplates!![nodeTemplateName] = nodeTemplateBuilder.build()
81     }
82
83     fun workflow(id: String, description: String, block: WorkflowBuilder.() -> Unit) {
84         if (workflows == null) workflows = hashMapOf()
85         workflows!![id] = WorkflowBuilder(id, description).apply(block).build()
86     }
87
88     fun workflow(workflow: Workflow) {
89         if (workflows == null) workflows = hashMapOf()
90         workflows!![workflow.id!!] = workflow
91     }
92
93     // TODO("populate inputs, outputs")
94     fun workflowNodeTemplate(
95         actionName: String,
96         nodeTemplateType: String,
97         description: String,
98         block: NodeTemplateBuilder.() -> Unit
99     ) {
100         if (nodeTemplates == null) nodeTemplates = hashMapOf()
101
102         if (workflows == null) workflows = hashMapOf()
103
104         val workflowBuilder = WorkflowBuilder(actionName, description)
105         workflowBuilder.nodeTemplateStep(actionName, description)
106         // Workflow name is NodeTemplate name
107         workflows!![actionName] = workflowBuilder.build()
108
109         nodeTemplates!![actionName] =
110             NodeTemplateBuilder(actionName, nodeTemplateType, description).apply(block).build()
111     }
112
113     fun build(): TopologyTemplate {
114         topologyTemplate.nodeTemplates = nodeTemplates
115         topologyTemplate.relationshipTemplates = relationshipTemplates
116         topologyTemplate.workflows = workflows
117         return topologyTemplate
118     }
119 }
120
121 open class NodeTemplateBuilder(
122     private val id: String,
123     private val type: String,
124     private val description: String? = ""
125 ) {
126
127     var nodeTemplate: NodeTemplate = NodeTemplate()
128     var properties: MutableMap<String, JsonNode>? = null
129     var interfaces: MutableMap<String, InterfaceAssignment>? = null
130     var artifacts: MutableMap<String, ArtifactDefinition>? = null
131     var capabilities: MutableMap<String, CapabilityAssignment>? = null
132     var requirements: MutableMap<String, RequirementAssignment>? = null
133
134     fun properties(properties: Map<String, JsonNode>) {
135         if (this.properties == null) this.properties = hashMapOf()
136         this.properties!!.putAll(properties)
137     }
138
139     fun properties(block: PropertiesAssignmentBuilder.() -> Unit) {
140         if (properties == null) properties = hashMapOf()
141         properties = PropertiesAssignmentBuilder().apply(block).build()
142     }
143
144     open fun <Prop : PropertiesAssignmentBuilder> typedProperties(block: Prop.() -> Unit) {
145         if (properties == null) properties = hashMapOf()
146         val instance: Prop = (block.reflect()?.parameters?.get(0)?.type?.classifier as KClass<Prop>).createInstance()
147         properties = instance.apply(block).build()
148     }
149
150     open fun <In : PropertiesAssignmentBuilder, Out : PropertiesAssignmentBuilder> typedOperation(
151         interfaceName: String,
152         description: String = "",
153         block: OperationAssignmentBuilder<In, Out>.() -> Unit
154     ) {
155         if (interfaces == null) interfaces = hashMapOf()
156
157         val interfaceAssignment = InterfaceAssignment()
158         val defaultOperationName = BluePrintConstants.DEFAULT_STEP_OPERATION
159         interfaceAssignment.operations = hashMapOf()
160         interfaceAssignment.operations!![defaultOperationName] =
161             OperationAssignmentBuilder<In, Out>(defaultOperationName, description).apply(block).build()
162         interfaces!![interfaceName] = interfaceAssignment
163     }
164
165     fun operation(
166         interfaceName: String,
167         description: String,
168         block: OperationAssignmentBuilder<PropertiesAssignmentBuilder, PropertiesAssignmentBuilder>.() -> Unit
169     ) {
170         typedOperation<PropertiesAssignmentBuilder, PropertiesAssignmentBuilder>(interfaceName, description, block)
171     }
172
173     fun artifact(id: String, type: String, file: String) {
174         if (artifacts == null) artifacts = hashMapOf()
175         artifacts!![id] = ArtifactDefinitionBuilder(id, type, file).build()
176     }
177
178     fun artifact(id: String, type: String, file: String, block: ArtifactDefinitionBuilder.() -> Unit) {
179         if (artifacts == null) artifacts = hashMapOf()
180         artifacts!![id] = ArtifactDefinitionBuilder(id, type, file).apply(block).build()
181     }
182
183     fun artifacts(artifacts: MutableMap<String, ArtifactDefinition>?) {
184         this.artifacts = artifacts
185     }
186
187     fun capability(id: String, block: CapabilityAssignmentBuilder.() -> Unit) {
188         if (capabilities == null) capabilities = hashMapOf()
189         capabilities!![id] = CapabilityAssignmentBuilder(id).apply(block).build()
190     }
191
192     fun capabilities(capabilities: MutableMap<String, CapabilityAssignment>) {
193         if (this.capabilities == null) this.capabilities = hashMapOf()
194         this.capabilities!!.putAll(capabilities)
195     }
196
197     fun requirement(id: String, capability: String, node: String, relationship: String) {
198         if (requirements == null) requirements = hashMapOf()
199         requirements!![id] = RequirementAssignmentBuilder(id, capability, node, relationship).build()
200     }
201
202     fun requirements(requirements: MutableMap<String, RequirementAssignment>) {
203         if (this.requirements == null) this.requirements = hashMapOf()
204         this.requirements!!.putAll(requirements)
205     }
206
207     open fun build(): NodeTemplate {
208         nodeTemplate.id = id
209         nodeTemplate.type = type
210         nodeTemplate.description = description
211         nodeTemplate.properties = properties
212         nodeTemplate.interfaces = interfaces
213         nodeTemplate.artifacts = artifacts
214         nodeTemplate.capabilities = capabilities
215         nodeTemplate.requirements = requirements
216         return nodeTemplate
217     }
218 }
219
220 open class RelationshipTemplateBuilder(
221     private val id: String,
222     private val type: String,
223     private val description: String? = ""
224 ) {
225     var relationshipTemplate: RelationshipTemplate = RelationshipTemplate()
226     var properties: MutableMap<String, JsonNode>? = null
227
228     fun properties(properties: Map<String, JsonNode>) {
229         if (this.properties == null) this.properties = hashMapOf()
230         this.properties!!.putAll(properties)
231     }
232
233     fun properties(block: PropertiesAssignmentBuilder.() -> Unit) {
234         if (properties == null) properties = hashMapOf()
235         properties = PropertiesAssignmentBuilder().apply(block).build()
236     }
237
238     fun property(id: String, value: Any) {
239         if (properties == null) properties = hashMapOf()
240         properties!![id] = value.asJsonType()
241     }
242
243     fun property(id: String, value: JsonNode) {
244         if (properties == null) properties = hashMapOf()
245         properties!![id] = value
246     }
247
248     fun copy(copy: String) {
249         relationshipTemplate.copy = copy
250     }
251
252     open fun <Prop : PropertiesAssignmentBuilder> typedProperties(block: Prop.() -> Unit) {
253         if (properties == null) properties = hashMapOf()
254         val instance: Prop = (block.reflect()?.parameters?.get(0)?.type?.classifier as KClass<Prop>).createInstance()
255         properties = instance.apply(block).build()
256     }
257
258     open fun build(): RelationshipTemplate {
259         relationshipTemplate.id = id
260         relationshipTemplate.type = type
261         relationshipTemplate.description = description
262         relationshipTemplate.properties = properties
263         return relationshipTemplate
264     }
265 }
266
267 class ArtifactDefinitionBuilder(private val id: String, private val type: String, private val file: String) {
268
269     private var artifactDefinition: ArtifactDefinition = ArtifactDefinition()
270     private var properties: MutableMap<String, JsonNode>? = null
271
272     fun repository(repository: String) {
273         artifactDefinition.repository = repository
274     }
275
276     fun deployPath(deployPath: String) {
277         artifactDefinition.deployPath = deployPath
278     }
279
280     fun properties(block: PropertiesAssignmentBuilder.() -> Unit) {
281         if (properties == null)
282             properties = hashMapOf()
283         properties = PropertiesAssignmentBuilder().apply(block).build()
284     }
285
286     fun build(): ArtifactDefinition {
287         artifactDefinition.id = id
288         artifactDefinition.type = type
289         artifactDefinition.file = file
290         artifactDefinition.properties = properties
291         return artifactDefinition
292     }
293 }
294
295 open class CapabilityAssignmentBuilder(private val id: String) {
296     var capabilityAssignment: CapabilityAssignment = CapabilityAssignment()
297     var attributes: MutableMap<String, JsonNode>? = null
298     var properties: MutableMap<String, JsonNode>? = null
299
300     fun attributes(block: AttributesAssignmentBuilder.() -> Unit) {
301         if (attributes == null) attributes = hashMapOf()
302         attributes = AttributesAssignmentBuilder().apply(block).build()
303     }
304
305     fun properties(block: PropertiesAssignmentBuilder.() -> Unit) {
306         if (properties == null) properties = hashMapOf()
307         properties = PropertiesAssignmentBuilder().apply(block).build()
308     }
309
310     fun property(id: String, value: Any) {
311         if (properties == null) properties = hashMapOf()
312         properties!![id] = value.asJsonType()
313     }
314
315     fun property(id: String, value: JsonNode) {
316         if (properties == null) properties = hashMapOf()
317         properties!![id] = value
318     }
319
320     open fun build(): CapabilityAssignment {
321         capabilityAssignment.properties = properties
322         capabilityAssignment.attributes = attributes
323         return capabilityAssignment
324     }
325 }
326
327 open class RequirementAssignmentBuilder(
328     private val id: String,
329     private val capability: String,
330     private val node: String,
331     private val relationship: String
332 ) {
333
334     private var requirementAssignment: RequirementAssignment = RequirementAssignment()
335
336     fun build(): RequirementAssignment {
337         requirementAssignment.id = id
338         requirementAssignment.capability = capability
339         requirementAssignment.node = node
340         requirementAssignment.relationship = relationship
341         return requirementAssignment
342     }
343 }
344
345 class InterfaceAssignmentBuilder(private val id: String) {
346
347     private var interfaceAssignment: InterfaceAssignment = InterfaceAssignment()
348     private var operations: MutableMap<String, OperationAssignment>? = null
349
350     fun operation(
351         id: String,
352         description: String? = "",
353         block: OperationAssignmentBuilder<PropertiesAssignmentBuilder, PropertiesAssignmentBuilder>.() -> Unit
354     ) {
355         if (operations == null)
356             operations = hashMapOf()
357         operations!![id] = OperationAssignmentBuilder<PropertiesAssignmentBuilder, PropertiesAssignmentBuilder>(
358             id, description
359         ).apply(block).build()
360     }
361
362     fun build(): InterfaceAssignment {
363         interfaceAssignment.id = id
364         interfaceAssignment.operations = operations
365         return interfaceAssignment
366     }
367 }
368
369 class OperationAssignmentBuilder<In : PropertiesAssignmentBuilder, Out : PropertiesAssignmentBuilder>(
370     private val id: String,
371     private val description: String? = ""
372 ) {
373
374     private var operationAssignment: OperationAssignment = OperationAssignment()
375
376     fun implementation(implementation: Implementation?) {
377         operationAssignment.implementation = implementation
378     }
379
380     fun implementation(timeout: Int, operationHost: String? = BluePrintConstants.PROPERTY_SELF) {
381         operationAssignment.implementation = Implementation().apply {
382             this.operationHost = operationHost!!
383             this.timeout = timeout
384         }
385     }
386
387     fun implementation(
388         timeout: Int,
389         operationHost: String? = BluePrintConstants.PROPERTY_SELF,
390         block: ImplementationBuilder.() -> Unit
391     ) {
392         operationAssignment.implementation = ImplementationBuilder(timeout, operationHost!!).apply(block).build()
393     }
394
395     fun inputs(inputs: MutableMap<String, JsonNode>?) {
396         operationAssignment.inputs = inputs
397     }
398
399     fun inputs(block: In.() -> Unit) {
400         val instance: In = (block.reflect()?.parameters?.get(0)?.type?.classifier as KClass<In>).createInstance()
401         operationAssignment.inputs = instance.apply(block).build()
402     }
403
404     fun outputs(outputs: MutableMap<String, JsonNode>?) {
405         operationAssignment.outputs = outputs
406     }
407
408     fun outputs(block: Out.() -> Unit) {
409         val instance: Out = (block.reflect()?.parameters?.get(0)?.type?.classifier as KClass<Out>).createInstance()
410         operationAssignment.outputs = instance.apply(block).build()
411     }
412
413     fun build(): OperationAssignment {
414         operationAssignment.id = id
415         operationAssignment.description = description
416         return operationAssignment
417     }
418 }
419
420 class ImplementationBuilder(private val timeout: Int, private val operationHost: String) {
421     private val implementation = Implementation()
422
423     fun primary(primary: String) {
424         implementation.primary = primary
425     }
426
427     fun dependencies(vararg dependencies: String) {
428         if (implementation.dependencies == null)
429             implementation.dependencies = arrayListOf()
430         dependencies.forEach {
431             implementation.dependencies!!.add(it)
432         }
433     }
434
435     fun build(): Implementation {
436         implementation.timeout = timeout
437         implementation.operationHost = operationHost
438         return implementation
439     }
440 }
441
442 open class PropertiesAssignmentBuilder {
443     var properties: MutableMap<String, JsonNode> = hashMapOf()
444
445     fun property(id: String, value: Any) {
446         property(id, value.asJsonType())
447     }
448
449     fun property(id: String, value: JsonNode) {
450         properties[id] = value
451     }
452
453     fun property(kProperty: KMutableProperty1<*, *>, value: JsonNode) {
454         properties[kProperty.name] = value
455     }
456
457     open fun build(): MutableMap<String, JsonNode> {
458         return properties
459     }
460 }
461
462 open class AttributesAssignmentBuilder {
463     var attributes: MutableMap<String, JsonNode> = hashMapOf()
464
465     fun attribute(id: String, value: String) {
466         attribute(id, value.asJsonType())
467     }
468
469     fun attribute(id: String, value: JsonNode) {
470         attributes[id] = value
471     }
472
473     fun build(): MutableMap<String, JsonNode> {
474         return attributes
475     }
476 }