All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.octopusden.octopus.components.registry.dsl.ComponentsRegistryDSL.kt Maven / Gradle / Ivy

package org.octopusden.octopus.components.registry.dsl

import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider
import org.octopusden.octopus.components.registry.api.build.BuildSystem
import org.octopusden.octopus.components.registry.api.build.tools.databases.DatabaseTool
import org.octopusden.octopus.components.registry.api.build.tools.products.ProductTool
import org.octopusden.octopus.components.registry.api.enums.BuildSystemType
import org.octopusden.octopus.components.registry.api.enums.ProductTypes
import org.octopusden.octopus.components.registry.api.enums.VcsTypes
import org.octopusden.octopus.components.registry.api.model.Dependencies
import org.octopusden.octopus.components.registry.dsl.jackson.JacksonFactory
import org.octopusden.octopus.components.registry.dsl.script.ComponentsRegistryScriptRunner
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.lang.IllegalArgumentException
import java.util.logging.Level
import java.util.logging.Logger
import org.octopusden.octopus.components.registry.api.beans.BuildBean
import org.octopusden.octopus.components.registry.api.beans.PTCProductToolBean
import org.octopusden.octopus.components.registry.api.beans.ClassicBuildSystem
import org.octopusden.octopus.components.registry.api.beans.ComponentBean
import org.octopusden.octopus.components.registry.api.beans.PTDDbProductToolBean
import org.octopusden.octopus.components.registry.api.beans.PTDProductToolBean
import org.octopusden.octopus.components.registry.api.beans.EscrowBean
import org.octopusden.octopus.components.registry.api.beans.GradleBuildBean
import org.octopusden.octopus.components.registry.api.beans.PTKProductToolBean
import org.octopusden.octopus.components.registry.api.beans.OdbcToolBean
import org.octopusden.octopus.components.registry.api.beans.OracleDatabaseToolBean
import org.octopusden.octopus.components.registry.api.beans.SubComponentBean
import org.octopusden.octopus.components.registry.api.beans.VersionedComponentConfigurationBean

private val logger = Logger.getLogger("org.octopusden.octopus.components.registry.dsl.ComponentsRegistryDSL")

val ANY_ARTIFACT = arrayOf(".*")

val GRADLE = BuildSystemType.GRADLE

val GIT = VcsTypes.GIT

val PT_K = ProductTypes.PT_K
val PT_C = ProductTypes.PT_C
val PT_D_DB = ProductTypes.PT_D_DB
val PT_D = ProductTypes.PT_D

open class SubComponentDSL(private val subComponent: SubComponentBean): VersionedComponentDSL(subComponent) {
    fun version(range: String, init: VersionedComponentDSL.() -> Unit) {
        val versionedComponent = clone(subComponent, VersionedComponentConfigurationBean::class.java)
        val versionedComponentDSL = VersionedComponentDSL(versionedComponent!!)
        versionedComponentDSL.init()
        subComponent.versions[range] = versionedComponent
    }
}

data class JiraComponent(var versionPrefix: String, var versionFormat: String)

data class Distribution(var explicit: Boolean, var external: Boolean)

open class ComponentDSL(private val parentComponent: ComponentBean): SubComponentDSL(parentComponent) {
    var productType = parentComponent.productType?.let { ComponentsRegistryScriptRunner.encodeParameters(it) }
        set(value) {
            parentComponent.productType = value?.let { ComponentsRegistryScriptRunner.decodeParameters(it) }
            field = value
        }

    var displayName = parentComponent.displayName
        set(value) {
            parentComponent.displayName = value
            field = value
        }
    fun components(init: ComponentsDSL.() -> Unit) {
        val components =  ComponentsDSL(parentComponent)
        components.init()
    }
}

class ComponentsDSL(private val parentComponent: ComponentBean) {
    fun component(key: String, init: SubComponentDSL.() -> Unit) {
        val subComponent = cloneCommonSections(parentComponent, SubComponentBean::class.java)
        subComponent.name = key
        val subComponentDSL = SubComponentDSL(subComponent)
        subComponentDSL.init()
        checkIntegrity("Component '$key' is already defined") { !parentComponent.subComponents.any { it.key == key} }
        parentComponent.subComponents[key] = subComponent
    }
}

open class VersionedComponentDSL(private val versionedComponent: VersionedComponentConfigurationBean) {
    var groupId = versionedComponent.groupId
        set(value) {
            versionedComponent.groupId = value
            field = value
        }

    var artifactId = versionedComponent.artifactIds
        set(value) {
            versionedComponent.artifactIds = value
            field = value
        }

    fun escrow(init: EscrowDSL.() -> Unit) {
        val escrowDsl = EscrowDSL(versionedComponent.escrow)
        escrowDsl.init()
    }

    fun build(init: BuildDSL.() -> Unit) {
        val buildDSL = BuildDSL()
        buildDSL.init()
        versionedComponent.setBuild(buildDSL.getBuild())
    }

    fun vcsSettings(vcsSettings: VcsSettingsDSL.() -> Unit) {
    }

    fun git(vcsSettings: GitSettingsDSL.() -> Unit) {
    }

    fun mercurial(vcsSettings: GitSettingsDSL.() -> Unit) {

    }

    fun jira(jira: JiraDSL.() -> Unit) {
    }

    fun distribution(distribution: Distribution.() -> Unit) {
    }
}

fun component(componentKey: String, init: ComponentDSL.() -> Unit) {
    val rootComponent = ComponentBean()
    rootComponent.name = componentKey
    val rootComponentDSL = ComponentDSL(rootComponent)
    rootComponentDSL.init()
    ComponentsRegistryScriptRunner.addRootComponent(rootComponent)
}

class GradleDSL(private val gradleBuild: GradleBuildBean) {
    var includeTestConfigurations = gradleBuild.includeTestConfigurations
        set(value) {
            gradleBuild.includeTestConfigurations = value
            field = value
        }

    /**
     * Override inherited included configuration.
     */
    var includeConfigurations: Collection = gradleBuild.includeConfigurations
        set(value) {
            gradleBuild.includeConfigurations = value
            field = value
        }

    /**
     * Override inherited excluded configuration.
     */
    var excludeConfigurations: Collection = gradleBuild.excludeConfigurations
        set(value) {
            gradleBuild.excludeConfigurations = value
            field = value
        }
    /**
     * Add gradle configuration to escrow. This configuration will be added to inherited including configurations.
     */
    fun includeConfiguration(configuration: String) {
        gradleBuild.includeConfigurations += configuration
    }

    /**
     * Remove gradle configuration from escrow. This configuration will be added to inherited excluding configurations.
     */
    fun excludeConfiguration(configuration: String) {
        gradleBuild.excludeConfigurations += configuration
    }
}


class EscrowDSL(private val escrow: EscrowBean) {
    var providedDependencies: Collection = escrow.providedDependencies
        set(value) {
            escrow.providedDependencies.clear()
            escrow.providedDependencies.addAll(value)
            field = escrow.providedDependencies
        }

    var additionalSources: Collection = escrow.additionalSources
        set(value) {
            escrow.additionalSources.clear()
            escrow.additionalSources.addAll(value)
            field = escrow.additionalSources
        }

    var buildTask: String? = escrow.buildTask
        set(value) {
            escrow.buildTask = value
            field = value
        }

    var reusable: Boolean = escrow.isReusable
        set(value) {
            escrow.isReusable = value
            field = value
        }

    fun gradle(dsl: GradleDSL.() -> Unit) {
        val gradleDSL = GradleDSL(escrow.gradle)
        gradleDSL.dsl()
    }

    var diskspace: Any? = escrow.diskSpaceRequirement.orElse(null)
        set(value) {
            when (value) {
                null -> {
                    escrow.setDiskspaceRequirement(value)
                }
                is Number -> {
                    escrow.setDiskspaceRequirement(value.toLong())
                }
                is String -> {
                    var multiplier = 1
                    if (value.endsWith("KB") || value.endsWith("K")) {
                        multiplier = 1024
                    } else if (value.endsWith("MB") || value.endsWith("M")) {
                        multiplier = 1024 * 1024
                    } else if (value.endsWith("GB") || value.endsWith("G")) {
                        multiplier = 1024 * 1024 * 1024
                    }
                    escrow.setDiskspaceRequirement(value.replace(Regex("(KB)|(K)|(MB)|(M)|(GB)|(G)"), "").toLong() * multiplier)
                }
                else -> {
                    throw IllegalArgumentException("Not supported type " + value::class.java)
                }
            }
            field = value
        }
}

class BuildSystemDSL {
    var type: BuildSystemType? = null
    var version: String? = null

    fun gradle() {
        type = BuildSystemType.GRADLE
    }

    internal fun getBuildSystem(): BuildSystem? {
        if (type != null) {
            return ClassicBuildSystem(type!!, version)
        }
        return null
    }
}

class BuildDSL {
    var javaVersion: String? = null
    private var build = BuildBean()
    private var buildSystem: BuildSystem? = null

    fun tools(dsl: ToolsDSL.() -> Unit) {
        val toolsDSL = ToolsDSL()
        toolsDSL.dsl()
        build = toolsDSL.getBuild()
    }

    fun buildSystem(dsl: BuildSystemDSL.() -> Unit) {
        val buildSystemDSL = BuildSystemDSL()
        buildSystemDSL.dsl()
        buildSystem = buildSystemDSL.getBuildSystem()
    }

    fun dependencies(init: DependenciesDSL.() -> Unit) {
        val dependenciesDSL = DependenciesDSL()
        dependenciesDSL.init()
        build.dependencies = dependenciesDSL.toDependencies()
    }

    internal fun getBuild(): BuildBean {
        javaVersion?.also { build.javaVersion = it }
        return build
    }
}

class ToolsDSL {
    private val build = BuildBean()
    fun database(init: DatabaseDSL.() -> Unit) {
        val databaseDSL = DatabaseDSL()
        databaseDSL.init()
        build.tools.addAll(databaseDSL.databaseTools)
    }

    fun product(init: ProductDSL.() -> Unit) {
        val productDSL = ProductDSL()
        productDSL.init()
        build.tools.addAll(productDSL.productTools)
    }

    fun odbc(init: OdbcToolBean.() -> Unit) {
        val odbcToolBean = OdbcToolBean()
        odbcToolBean.init()
        build.tools.add(odbcToolBean)
    }

    internal fun getBuild(): BuildBean {
        //TODO Perform merge with parent
        return build
    }
}

class OdbcDSL {
    var version: String = "12.2"
}

class DatabaseDSL {
    internal val databaseTools = ArrayList()
    fun oracle(init: OracleDSL.() -> Unit) {
        val oracleDSL = OracleDSL()
        oracleDSL.init()
        val oracleDatabaseTool = OracleDatabaseToolBean()
        oracleDatabaseTool.version = oracleDSL.version
        checkIntegrity("More than one oracle database is set") { databaseTools.isEmpty() }
        databaseTools.add(oracleDatabaseTool)
    }
}

class OctopusProductDSL {
    var version: String? = null
}

class OracleDSL {
    var version: String? = null
}

class ProductDSL {
    internal val productTools = ArrayList()

    fun type(name: String, init: OctopusProductDSL.() -> Unit) {
        val productType = ComponentsRegistryScriptRunner.decodeParameters(name)
        val product = OctopusProductDSL()
        product.init()
        val componentProduct = when(productType) {
            ProductTypes.PT_C -> PTCProductToolBean()
            ProductTypes.PT_K -> PTKProductToolBean()
            ProductTypes.PT_D_DB -> PTDDbProductToolBean()
            ProductTypes.PT_D -> PTDProductToolBean()
        }
        componentProduct.version = product.version
        checkIntegrity("More than one COMPONENT product is set") { !productTools.any { it.type == productType } }
        productTools.add(componentProduct)
    }

}

open class VcsSpecificationDSL {
    lateinit var vcsUrl: String
    var branch: String? = null
    var tag: String? = null
}

open class VcsSettingsDSL: VcsSpecificationDSL {
    constructor() : super()
    constructor(repositoryType: VcsTypes) : super() {
        this.repositoryType = repositoryType
    }
    lateinit var repositoryType: VcsTypes
}

class GitSettingsDSL: VcsSettingsDSL(VcsTypes.GIT)
class MercurialSettingsDSL: VcsSettingsDSL(VcsTypes.MERCURIAL)

class JiraDSL {
    var projectKey: String? = null
    var majorVersionFormat: String? = null
    var releaseVersionFormat: String? = null
    var buildVersionFormat: String? = null
    var technical = false
    fun component(jiraComponent: JiraComponent.()-> Unit) {
    }
}

class DistributionDSL {
    var projectKey: String? = null
    var majorVersionFormat: String? = null
    var releaseVersionFormat: String? = null
    fun component(jiraComponent: JiraComponent.()-> Unit) {
    }
}

class DependenciesDSL {
    var autoUpdate: Boolean = false

    internal fun toDependencies(): Dependencies =
        Dependencies(autoUpdate)

}

class SettingsDSL {
    var param1: String = ""
}

fun throwException(message: String) {
    //TODO Log registry path to problem
    throw RuntimeException(message)
}

fun checkIntegrity(message: String, closure: () -> Boolean) {
    if (!closure()) {
        throwException(message)
    }
}

internal fun  clone(source: Any?, clazz: Class): T? {
    if (source == null) {
        return null
    }
    val mapper = JacksonFactory.instance.objectMapper
    val outputStream = ByteArrayOutputStream()
    val componentCloneFilter = SimpleBeanPropertyFilter.serializeAllExcept("subComponents", "versions", "name", "displayName", "productType")
    val filters = SimpleFilterProvider().addFilter("cloneFilter", componentCloneFilter)
    mapper.writer(filters).writeValue(outputStream, source)
    if (logger.isLoggable(Level.FINE)) {
        logger.fine("Clone json for $clazz is ${String(outputStream.toByteArray())}")
    }
    return mapper.readValue(ByteArrayInputStream(outputStream.toByteArray()), clazz)
}

internal fun  cloneCommonSections(source: T, clazz: Class): T {
    val component = clazz.getDeclaredConstructor().newInstance()
    //Copy all properties which should be inherited, e.g. jira section
    component.setBuild(clone(source.build, BuildBean::class.java))
    return component
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy