package unibz.cs.semint.kprime.domain.ddl import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement @JacksonXmlRootElement(localName = "schema") class Schema () { @JacksonXmlProperty(isAttribute = true) var name: String ="" @JacksonXmlProperty(isAttribute = true) var id: String="" var tables= ArrayList<Table>() var constraints= ArrayList<Constraint>() fun table(name: String): Table? { if (tables.isEmpty()) return null return tables.filter { t -> t.name==name }.firstOrNull() } fun constraint(name: String): Constraint? { if (constraints.isEmpty()) return null return constraints.filter { c -> c.name==name}.firstOrNull() } fun key(tableName: String): Set<Column> { var resultCols = mutableSetOf<Column>() val first = constraints.filter { c -> c.type == Constraint.TYPE.PRIMARY_KEY.name && c.name == "primaryKey.${tableName}" }.toList() if (first.isEmpty()) return mutableSetOf() return first[0].source.columns.toSet() } fun functionalLHS(tableName: String): Set<Column> { var resultCols = mutableSetOf<Column>() val first = constraints.filter { c -> c.type == Constraint.TYPE.FUNCTIONAL.name && c.name == "functional.${tableName}" }.toList() if (first.isEmpty()) return mutableSetOf() return first[0].source.columns.toSet() } fun functionals(): Set<Constraint> { var resultCols = mutableSetOf<Column>() return constraints.filter { c -> c.type == Constraint.TYPE.FUNCTIONAL.name }.toSet() } fun functionalRHS(tableName: String): Set<Column> { var resultCols = mutableSetOf<Column>() val first = constraints.filter { c -> c.type == Constraint.TYPE.FUNCTIONAL.name && c.name == "functional.${tableName}" }.toList() if (first.isEmpty()) return mutableSetOf() return first[0].target.columns.toSet() } fun key(tableName:String,k:Set<Column>) { val primaryConstraint = Constraint() primaryConstraint.name="primaryKey.$tableName" primaryConstraint.source.table="$tableName" primaryConstraint.source.columns.addAll(k) primaryConstraint.type= Constraint.TYPE.PRIMARY_KEY.name constraints.add(primaryConstraint) } fun functional(tableName:String, lhs:Set<Column>, rhs:Set<Column>){ val functionalConstraint = Constraint() functionalConstraint.name="functional.$tableName" functionalConstraint.source.table="$tableName" functionalConstraint.source.columns.addAll(lhs) functionalConstraint.target.table="$tableName" functionalConstraint.target.columns.addAll(rhs) functionalConstraint.type= Constraint.TYPE.FUNCTIONAL.name constraints.add(functionalConstraint) } companion object { fun <T> reducedPowerSet(originalSet: Set<T>): Set<Set<T>> { var result = powerSet(originalSet) result = result.minus(HashSet<T>()) as Set<Set<T>> return result } private fun <T> powerSet(originalSet: Set<T>): Set<Set<T>> { val sets = HashSet<Set<T>>() if (originalSet.isEmpty()) { sets.add(HashSet<T>()) return sets } val list = ArrayList<T>(originalSet) val head = list.get(0) val rest = HashSet<T>(list.subList(1,list.size)) for (set in powerSet(rest)) { val newSet = HashSet<T>() newSet.add(head) newSet.addAll(set) sets.add(newSet) sets.add(set) } return sets } fun superkeys(attrs: Set<Column>, fds:Set<Constraint>): Set<Set<Column>> { val keys = HashSet<Set<Column>>() val powerset = reducedPowerSet(attrs) for (sa in powerset) { if (closure(sa, fds).equals(attrs)) { keys.add(sa) } } return keys } fun closure(attrs: Set<Column>,fds:Set<Constraint>): Set<Column> { val result = HashSet<Column>(attrs) //println("RESULT = $result") var found = true while(found) { found= false for (fd in fds) { //println("FD ${fd.left()} == ${fd.right()}") if (result.containsAll(fd.left()) && !result.containsAll(fd.right())) { result.addAll(fd.right()) found = true //println("FOUND") } } } return result } fun keys(attrs: Set<Column>, fds:Set<Constraint>): Set<Set<Column>> { var superkeys = superkeys(attrs, fds) var toremove = HashSet<Set<Column>>() for (key in superkeys) { for (col in key) { var remaining = HashSet<Column>(key) remaining.remove(col) if (superkeys.contains(remaining)) { toremove.add(key) break } } } superkeys = superkeys.minus(toremove) return superkeys } } }