Skip to content
Snippets Groups Projects
HSplitUseCase.kt 4.07 KiB
package unibz.cs.semint.kprime.usecase

import unibz.cs.semint.kprime.adapter.service.XMLSerializerJacksonAdapter
import unibz.cs.semint.kprime.domain.*
import unibz.cs.semint.kprime.domain.ddl.Column
import unibz.cs.semint.kprime.domain.ddl.Constraint
import unibz.cs.semint.kprime.domain.ddl.Database
import unibz.cs.semint.kprime.domain.ddl.Table

class HSplitUseCase {

    fun compute(databaseMetadata: Database) {
        printDb(databaseMetadata)
        val  detected = detect(databaseMetadata)
        if (detected.ok!=null) {
            val applied = apply(databaseMetadata, detected)
            if (applied.ok!=null) {
                printDb(applied.ok)
                printSql(SQLizeUseCase().sqlize(applied.ok))
            }

        }
    }

    private fun printSql(sqlines: List<String>) {
        println()
        println("--------------------------------------------------------------------------")
        for (sql in sqlines) println(sql)
    }

    private fun printDb(db: Database) {
        println()
        println("--------------------------------------------------------------------------")
        println(XMLSerializeUseCase(XMLSerializerJacksonAdapter()).prettyDatabase(db))
    }

    private fun detect(personMetadata: Database): UseCaseResult<Database> {
        val dbDetected = Database()
        // Check if it has nullable column.
        for (table in personMetadata.schema.tables) {
            if (table.hasNullable()) {
                // then this table has to be partitioned to remove nullable.
                // adds this table to db to apply vertical partitioning.
                dbDetected.schema.tables.add(table)
            }
        }
        return UseCaseResult("done detect",dbDetected)
    }

    private fun apply(personMetadata: Database, detected: UseCaseResult<Database>): UseCaseResult<Database>{
        // pure person
        val table = Table()
        table.name= "pure_person"
        table.view="person"
        table.condition="person.T=null AND person.S=null"
        personMetadata.schema.tables.add(table)
        val colSSN = Column("SSN", "id.SSN", "dbname.SSN")
        colSSN.nullable=false
        table.columns.add(colSSN)

        // person with only telephone
        val tableWithT = Table()
        tableWithT.view="person"
        tableWithT.name= "person_with_T"
        tableWithT.condition="person.T NOT null AND person.S=null"
        personMetadata.schema.tables.add(tableWithT)
        val colT = Column("T", "id.T", "dbname.T")
        colT.nullable=false
        tableWithT.columns.add(colSSN)
        tableWithT.columns.add(colT)

        // person with only TS
        val tableWithS = Table()
        tableWithS.view="person"
        tableWithS.name= "person_with_TS"
        tableWithS.condition="person.T = null AND person.S NOT null"
        personMetadata.schema.tables.add(tableWithS)
        val colS = Column("S", "id.S", "dbname.S")
        colS.nullable=false
        tableWithS.columns.add(colSSN)
        tableWithS.columns.add(colS)


        // person with only S
        val tableWithTS = Table()
        tableWithTS.view="person"
        tableWithTS.name= "person_with_S"
        tableWithTS.condition="person.T NOT null AND person.S NOT null"
        personMetadata.schema.tables.add(tableWithTS)
        tableWithTS.columns.add(colSSN)
        tableWithTS.columns.add(colT)
        tableWithTS.columns.add(colS)

        // removes table person
        val personTable = personMetadata.schema.table("person")
        personMetadata.schema.tables.remove(personTable)

        // removes constraints from/to person
        var contraintsToRemove = mutableSetOf<Constraint>()
        for (contraint in personMetadata.schema.constraints) {
            if (contraint.source.table=="person") {
                contraintsToRemove.add(contraint)
            }
            if (contraint.target.table=="person") {
                contraintsToRemove.add(contraint)
            }
        }
        personMetadata.schema.constraints.removeAll(contraintsToRemove)

        // add constraint partition
        return UseCaseResult("done apply", personMetadata)
    }
}