From 9af5a1747aabd854f325f3effe5d6419fb8bd82c Mon Sep 17 00:00:00 2001
From: npedot <nicola.pedot@gmail.com>
Date: Thu, 23 Jan 2020 14:32:34 +0100
Subject: [PATCH] adds kprime transfomer v3 xpath alfa

---
 .attach_pid21233                              |  0
 .../scenario/PersonXPathScenarioTI.kt         | 95 ++++++++++++++++---
 src/test/resources/db/person.xml              |  8 ++
 src/test/resources/db/person_out.template     | 49 ----------
 .../vertical/decompose/person.paths           |  6 ++
 .../vertical/decompose/person_out.template    | 67 +++++++++++++
 6 files changed, 164 insertions(+), 61 deletions(-)
 create mode 100644 .attach_pid21233
 delete mode 100644 src/test/resources/db/person_out.template
 create mode 100644 src/test/resources/transformer/vertical/decompose/person.paths
 create mode 100644 src/test/resources/transformer/vertical/decompose/person_out.template

diff --git a/.attach_pid21233 b/.attach_pid21233
new file mode 100644
index 0000000..e69de29
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 ec92474..743b8c7 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 40ddf5e..8a51812 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 7468553..0000000
--- 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 0000000..d65ba38
--- /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 0000000..fcb9fbf
--- /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>
-- 
GitLab