diff --git a/.attach_pid21233 b/.attach_pid21233 new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/test/kotlin/unibz.cs.semint.kprime/scenario/PersonXPathScenarioTI.kt b/src/test/kotlin/unibz.cs.semint.kprime/scenario/PersonXPathScenarioTI.kt index ec92474965909217b550585ffd68ae5046cfe9c3..743b8c76dd975288775a68c0c3e91cb3df3a0ee2 100644 --- a/src/test/kotlin/unibz.cs.semint.kprime/scenario/PersonXPathScenarioTI.kt +++ b/src/test/kotlin/unibz.cs.semint.kprime/scenario/PersonXPathScenarioTI.kt @@ -2,9 +2,13 @@ package unibz.cs.semint.kprime.scenario import freemarker.cache.ClassTemplateLoader import freemarker.template.Configuration -import freemarker.template.Template import org.junit.Test +import org.w3c.dom.NodeList import java.io.OutputStreamWriter +import java.util.* +import javax.xml.parsers.DocumentBuilderFactory +import javax.xml.xpath.XPathConstants +import javax.xml.xpath.XPathFactory class PersonXPathScenarioTI { @@ -13,27 +17,94 @@ class PersonXPathScenarioTI { // given // input person db val personDbXml = PersonXPathScenarioTI::class.java.getResource("/db/person.xml").readText() + val personDbStream = PersonXPathScenarioTI::class.java.getResourceAsStream("/db/person.xml") + val personProperties = PersonXPathScenarioTI::class.java.getResourceAsStream("/transformer/vertical/decompose/person.paths") //println(personDbXml) // input person out template - val personTemplate = PersonXPathScenarioTI::class.java.getResource("/db/person_out.template").readText() + //val personTemplate = PersonXPathScenarioTI::class.java.getResource("<database name=\"\" id=\"\">\n <schema name=\"\" id=\"\">\n <tables>\n <tables name=\"person1\" id=\"\" view=\"\" condition=\"\">\n <columns>\n <#list keys as key>\n <columns name=${key} id=\"id.${key}\" nullable=\"false\" dbtype=\"\"/>\n </#list>\n <#list lhss as lhs>\n <columns name=\"${lhs}\" id=\"id.${lhs}\" nullable=\"false\" dbtype=\"\"/>\n </#list>\n <#list rests as rest>\n <columns name=\"${rest}\" id=\"id.${rest}\" nullable=\"true\" dbtype=\"\"/>\n </#list>\n </columns>\n </tables>\n <tables name=\"person2\" id=\"\" view=\"\" condition=\"\">\n <columns>\n <#list lhss as lhs>\n <columns name=\"${lhs}\" id=\"id.${lhs}\" nullable=\"false\" dbtype=\"\"/>\n </#list>\n <#list rhss as rhs>\n <columns name=\"${rhs}\" id=\"id.${rhs}\" nullable=\"false\" dbtype=\"\"/>\n </#list>\n </columns>\n </tables>\n </tables>\n <constraints>\n <constraints name=\"primaryKey.person\" id=\"\" type=\"PRIMARY_KEY\">\n <source name=\"\" id=\"\" table=\"person\">\n <columns>\n <columns name=\"SSN\" id=\"id.SSN\" dbname=\"dbname.SSN\" nullable=\"false\" dbtype=\"\"/>\n </columns>\n </source>\n <target name=\"\" id=\"\" table=\"\">\n <columns/>\n </target>\n </constraints>\n <constraints name=\"functional.person\" id=\"\" type=\"FUNCTIONAL\">\n <source name=\"\" id=\"\" table=\"person\">\n <columns>\n <columns name=\"T\" id=\"id.T\" dbname=\"dbname.T\" nullable=\"false\" dbtype=\"\"/>\n </columns>\n </source>\n <target name=\"\" id=\"\" table=\"person\">\n <columns>\n <columns name=\"S\" id=\"id.S\" dbname=\"dbname.S\" nullable=\"true\" dbtype=\"\"/>\n </columns>\n </target>\n </constraints>\n </constraints>\n </schema>\n</database>\n").readText() //println(personTemplate) + val personPaths = Properties() + personPaths.load(personProperties) + + val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder() + val doc = docBuilder.parse(personDbStream) + val xpath = XPathFactory.newInstance().newXPath() + + val xpathResult = xpath.compile("/database/schema/tables/tables/columns/columns[2]/@name").evaluate(doc) + println(xpathResult) + + val xpathResultNodes = asValueList(xpath.compile("/database/schema/tables/tables[@name='person1']/columns/columns/@name").evaluate(doc, XPathConstants.NODESET) as NodeList) + println(xpathResultNodes) + // extract vars as value attributes via xpaths - val keys = listOf<String>("SSN") - val lhss = listOf<String>("T") - val rhss = listOf<String>("S") - val rests = listOf<String>("X") // use vars in template val templConfig = Configuration(Configuration.VERSION_2_3_29) val classTemplLoader = ClassTemplateLoader(PersonXPathScenarioTI::javaClass.javaClass,"/") templConfig.templateLoader= classTemplLoader - val templModel = mapOf<String,Any>( - "keys" to keys, - "lhss" to lhss, - "rhss" to rhss, - "rests" to rests) + val templModel = mutableMapOf<String,Any>() + + // compute xpath lists + for (entryNameas in personPaths.propertyNames() ) + { + val name = entryNameas as String + val value = personPaths.getProperty(name) + if (!(value.startsWith("-") || value.startsWith("+"))) { + templModel[name] = asValueList(xpath.compile(value).evaluate(doc, XPathConstants.NODESET) as NodeList) + println(" ${name} = ${value}") + println(" ${name} = ${templModel[name]}") + } + } + // compute derived list sum and minus + for (entryNameas in personPaths.propertyNames() ) + { + val name = entryNameas as String + val value = personPaths.getProperty(name) + if (value.startsWith("-") || value.startsWith("+")) { + println(" ${name} = ${value}") + templModel[name] = computeDerivedList(templModel,value) + } + } val templ = //Template.getPlainTextTemplate("templ1",personTemplate,templConfig) - templConfig.getTemplate("db/person_out.template") + templConfig.getTemplate("transformer/vertical/decompose/person_out.template") val out = OutputStreamWriter(System.out) templ.process(templModel,out) } + + + private fun computeDerivedList(templModel: MutableMap<String, Any>, derivationRule: String): Any { + var derivedList = mutableListOf<String>() + // if derivationRule starts with + then compute union + val splittedRule = derivationRule.split(" ") + if (splittedRule[0]=="+") { + val sourceLists = splittedRule.drop(1) + println(sourceLists) + derivedList.addAll(templModel[sourceLists[0]] as List<String>) + for (i in 1..(sourceLists.size-1)) { + derivedList = derivedList.plus(templModel[sourceLists[i]] as MutableList<String>) as MutableList<String> + } + println(derivedList) + } + if (splittedRule[0]=="-") { + //println(splittedRule) + val sourceLists = splittedRule.drop(1) + //println(sourceLists) + derivedList.addAll(templModel[sourceLists[0]] as List<String>) + for (i in 1..(sourceLists.size-1)) { + derivedList = derivedList.minus(templModel[sourceLists[i]] as MutableList<String>) as MutableList<String> + } + println(" $derivedList") + } + // if derivationRule starts with - then compute intersection + return derivedList + } + + private fun asValueList(xpathResultNodes: NodeList): MutableList<String> { + val listNodeValues = mutableListOf<String>() + for (nodeId in 0..xpathResultNodes.length) { + val item = xpathResultNodes.item(nodeId) + if (item==null) continue + listNodeValues.add(item.nodeValue) + } + return listNodeValues + } } \ No newline at end of file diff --git a/src/test/resources/db/person.xml b/src/test/resources/db/person.xml index 40ddf5e55535d5ab076b5b3cea9bd3fae1c40c6a..8a5181255646bfd02af24e0f53f7fc9998b6c558 100644 --- a/src/test/resources/db/person.xml +++ b/src/test/resources/db/person.xml @@ -9,6 +9,14 @@ <columns name="X" id="id.X" dbname="dbname.X" nullable="true" dbtype=""/> </columns> </tables> + <tables name="person2" id="" view="" condition=""> + <columns> + <columns name="SSN2" id="id.SSN" dbname="dbname.SSN" nullable="false" dbtype=""/> + <columns name="T2" id="id.T" dbname="dbname.T" nullable="false" dbtype=""/> + <columns name="S2" id="id.S" dbname="dbname.S" nullable="true" dbtype=""/> + <columns name="X2" id="id.X" dbname="dbname.X" nullable="true" dbtype=""/> + </columns> + </tables> </tables> <constraints> <constraints name="primaryKey.person" id="" type="PRIMARY_KEY"> diff --git a/src/test/resources/db/person_out.template b/src/test/resources/db/person_out.template deleted file mode 100644 index 7468553ab67e5816a7a66776831ef832c119014e..0000000000000000000000000000000000000000 --- a/src/test/resources/db/person_out.template +++ /dev/null @@ -1,49 +0,0 @@ -<database name="" id=""> - <schema name="" id=""> - <tables> - <tables name="person1" id="" view="" condition=""> - <columns> - <#list keys as key> - <columns name=${key} id="id.${key}" nullable="false" dbtype=""/> - </#list> - <#list lhss as lhs> - <columns name="${lhs}" id="id.${lhs}" nullable="false" dbtype=""/> - </#list> - <#list rests as rest> - <columns name="${rest}" id="id.${rest}" nullable="true" dbtype=""/> - </#list> - </columns> - </tables> - <tables name="person2" id="" view="" condition=""> - <columns> - <columns name="T" id="id.T" dbname="dbname.T" nullable="false" dbtype=""/> - <columns name="S" id="id.S" dbname="dbname.S" nullable="true" dbtype=""/> - </columns> - </tables> - </tables> - <constraints> - <constraints name="primaryKey.person" id="" type="PRIMARY_KEY"> - <source name="" id="" table="person"> - <columns> - <columns name="SSN" id="id.SSN" dbname="dbname.SSN" nullable="false" dbtype=""/> - </columns> - </source> - <target name="" id="" table=""> - <columns/> - </target> - </constraints> - <constraints name="functional.person" id="" type="FUNCTIONAL"> - <source name="" id="" table="person"> - <columns> - <columns name="T" id="id.T" dbname="dbname.T" nullable="false" dbtype=""/> - </columns> - </source> - <target name="" id="" table="person"> - <columns> - <columns name="S" id="id.S" dbname="dbname.S" nullable="true" dbtype=""/> - </columns> - </target> - </constraints> - </constraints> - </schema> -</database> diff --git a/src/test/resources/transformer/vertical/decompose/person.paths b/src/test/resources/transformer/vertical/decompose/person.paths new file mode 100644 index 0000000000000000000000000000000000000000..d65ba38688aad5d87cc685ef9bfc73463daa95e6 --- /dev/null +++ b/src/test/resources/transformer/vertical/decompose/person.paths @@ -0,0 +1,6 @@ +all=/database/schema/tables/tables[@name='person']/columns/columns/@name +keys=/database/schema/constraints/constraints[@type='PRIMARY_KEY']/source/columns/columns/@name +lhss=/database/schema/constraints/constraints[@type='FUNCTIONAL']/source/columns/columns/@name +rhss=/database/schema/constraints/constraints[@type='FUNCTIONAL']/target/columns/columns/@name +rests=- all keys lhss rhss +table=/database/schema/tables/tables[@name='person']/@name \ No newline at end of file diff --git a/src/test/resources/transformer/vertical/decompose/person_out.template b/src/test/resources/transformer/vertical/decompose/person_out.template new file mode 100644 index 0000000000000000000000000000000000000000..fcb9fbf67ad6a35ce30c1530076541b373ba1e47 --- /dev/null +++ b/src/test/resources/transformer/vertical/decompose/person_out.template @@ -0,0 +1,67 @@ +<database name="" id=""> + <schema name="" id=""> + <tables> + <tables name="${table[0]}1" id="" view="" condition=""> + <columns> + <#list keys as key> + <columns name=${key} id="id.${key}" nullable="false" dbtype=""/> + </#list> + <#list lhss as lhs> + <columns name="${lhs}" id="id.${lhs}" nullable="false" dbtype=""/> + </#list> + <#list rests as rest> + <columns name="${rest}" id="id.${rest}" nullable="true" dbtype=""/> + </#list> + </columns> + </tables> + <tables name="${table[0]}2" id="" view="" condition=""> + <columns> + <#list lhss as lhs> + <columns name="${lhs}" id="id.${lhs}" nullable="false" dbtype=""/> + </#list> + <#list rhss as rhs> + <columns name="${rhs}" id="id.${rhs}" nullable="false" dbtype=""/> + </#list> + </columns> + </tables> + </tables> + <constraints> + <constraints name="primaryKey.${table[0]}1" id="" type="PRIMARY_KEY"> + <source name="" id="" table="${table[0]}1"> + <columns> + <#list keys as key> + <columns name="${key}" id="id.${key}" dbname="dbname.${key}" nullable="false" dbtype=""/> + </#list> + </columns> + </source> + <target name="" id="" table=""> + <columns/> + </target> + </constraints> + <constraints name="primaryKey.${table[0]}2" id="" type="PRIMARY_KEY"> + <source name="" id="" table="${table[0]}2"> + <columns> + <#list lhss as lhs> + <columns name="${lhs}" id="id.${lhs}" dbname="dbname.${lhs}" nullable="false" dbtype=""/> + </#list> + </columns> + </source> + <target name="" id="" table=""> + <columns/> + </target> + </constraints> + <constraints name="functional.${table[0]}" id="" type="BIFUNCTIONAL"> + <source name="" id="" table="${table[0]}1"> + <#list lhss as lhs> + <columns name="${lhs}" id="id.${lhs}" dbname="dbname.${lhs}" nullable="false" dbtype=""/> + </#list> + </source> + <target name="" id="" table="${table[0]}2"> + <#list lhss as lhs> + <columns name="${lhs}" id="id.${lhs}" dbname="dbname.${lhs}" nullable="false" dbtype=""/> + </#list> + </target> + </constraints> + </constraints> + </schema> +</database>