Skip to content

Commit

Permalink
Merge pull request #14 from objectionary/transform
Browse files Browse the repository at this point in the history
Add aoi section to xmirs
  • Loading branch information
OlesiaSub authored Oct 29, 2022
2 parents 98115fd + 9d22d9e commit 1858042
Show file tree
Hide file tree
Showing 8 changed files with 455 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
object-inference.iml
.idea
target
target
*TMP/
5 changes: 5 additions & 0 deletions src/main/kotlin/org/objectionary/aoi/launch/Launcher.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.objectionary.aoi.launch

import org.objectionary.aoi.process.InnerUsageProcessor
import org.objectionary.aoi.process.InstanceUsageProcessor
import org.objectionary.aoi.transformer.XmirTransformer
import org.objectionary.ddr.graph.AttributesSetter
import org.objectionary.ddr.graph.CondAttributesSetter
import org.objectionary.ddr.graph.InnerPropagator
Expand All @@ -27,4 +29,7 @@ fun launch(path: String) {
val innerPropagator = InnerPropagator(graph)
innerPropagator.propagateInnerAttrs()
InnerUsageProcessor(graph).processInnerUsages()
InstanceUsageProcessor(graph).processInstanceUsages()
val transformer = XmirTransformer(graph, documents)
transformer.addAoiSection()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package org.objectionary.aoi.transformer

import org.objectionary.aoi.data.FreeAttributesHolder
import org.objectionary.ddr.graph.name
import org.objectionary.ddr.graph.repr.Graph
import org.w3c.dom.Document
import org.w3c.dom.Element
import org.w3c.dom.Node
import java.io.FileOutputStream
import java.io.OutputStream
import java.io.UnsupportedEncodingException
import javax.xml.transform.OutputKeys
import javax.xml.transform.TransformerException
import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult
import javax.xml.transform.stream.StreamSource

/**
* Transforms xmir documents by adding an aoi section to each of them
*/
class XmirTransformer(
private val graph: Graph,
private val documents: MutableMap<Document, String>
) {
/**
* Aggregates the process of adding an aoi section to xmir documents
*/
fun addAoiSection() {
documents.forEach { doc ->
val program = doc.key.getElementsByTagName("program").item(0)
val aoiChild: Element = doc.key.createElement("aoi")
addAoiChildren(aoiChild)
program.appendChild(aoiChild)
}
transformDocuments()
}

@Suppress("CUSTOM_LABEL")
private fun addAoiChildren(parent: Element) {
FreeAttributesHolder.storage
.filter { it.holderObject.ownerDocument == parent.ownerDocument }
.forEach { el ->
val obj = parent.ownerDocument.createElement("obj")
val fqn = getFqn(el.name, el.holderObject)
obj.setAttribute("fqn", fqn)
val inferred: Element = parent.ownerDocument.createElement("inferred")
graph.igNodes.filter { node ->
node.name ?: return@filter false
for (attr in el.appliedAttributes) {
// @todo #14:30min differentiate not only by name but also by the number of parameters
node.attributes.find { it.name == attr.name.substring(1) } ?: return@filter false
}
return@filter true
}.forEach {
val element = parent.ownerDocument.createElement("obj")
val name = getFqn(it.name!!, it.body.parentNode)
element.setAttribute("fqn", name)
inferred.appendChild(element)
}
obj.appendChild(inferred)
parent.appendChild(obj)
}
}

private fun getFqn(name: String, par: Node): String {
var fqn = name
var parent = par
while (name(parent) != null) {
fqn = "${name(parent)}.$fqn"
parent = parent.parentNode
}
return fqn
}

private fun transformDocuments() {
documents.forEach { doc ->
val outputStream = FileOutputStream(doc.value)
outputStream.use { writeXml(it, doc.key) }
}
}

/**
* Writes transformed [document] to [output]
*
* @param document transformed document
* @param output where to write the result
*/
@Throws(TransformerException::class, UnsupportedEncodingException::class)
private fun writeXml(output: OutputStream, document: Document) {
val prettyPrintXlst = this.javaClass.getResourceAsStream("pretty_print.xslt")
val transformer = TransformerFactory.newInstance().newTransformer(StreamSource(prettyPrintXlst))
transformer.setOutputProperty(OutputKeys.INDENT, "yes")
transformer.setOutputProperty(OutputKeys.STANDALONE, "no")
val source = DOMSource(document)
val result = StreamResult(output)
transformer.transform(source, result)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.objectionary.aoi.integration

import org.junit.jupiter.api.Test

class IntegrationTest : IntegrationTestBase() {
@Test
fun `test basic`() = doTest()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2022 Olesia Subbotina
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package org.objectionary.aoi.integration

import org.objectionary.aoi.TestBase
import org.objectionary.aoi.launch.launch
import org.objectionary.ddr.launch.documents
import org.apache.commons.io.FileUtils
import org.slf4j.LoggerFactory
import java.io.BufferedReader
import java.io.File
import java.nio.file.Files
import java.nio.file.Paths

/**
* Base class for testing decorators resolver
*/
open class IntegrationTestBase : TestBase {
private val logger = LoggerFactory.getLogger(this.javaClass.name)

override fun doTest() {
val path = getTestName()
documents.clear()
launch(constructInPath(path))
val actualFiles: MutableList<String> = mutableListOf()
Files.walk(Paths.get(constructOutPath(path)))
.filter(Files::isRegularFile)
.forEach { actualFiles.add(it.toString()) }
Files.walk(Paths.get(constructResultPath(path)))
.filter(Files::isRegularFile)
.forEach { file ->
val actualBr: BufferedReader = File(file.toString()).bufferedReader()
val actual = actualBr.use { it.readText() }.replace(" ", "")
val expectedFile = actualFiles.find {
it.replace("out$sep", "in$sep").replaceFirst(path, "${path}_ddr") == file.toString()
}
val expectedBr: BufferedReader = File(expectedFile.toString()).bufferedReader()
val expected = expectedBr.use { it.readText() }.replace(" ", "")
checkOutput(expected, actual)
}
try {
val tmpDir =
Paths.get((constructResultPath(path))).toString()
FileUtils.deleteDirectory(File(tmpDir))
} catch (e: Exception) {
logger.error(e.printStackTrace().toString())
}
}

override fun constructOutPath(directoryName: String): String =
File(System.getProperty("user.dir")).resolve(
File("src${sep}test${sep}resources${sep}integration${sep}out$sep$directoryName")
).absolutePath.replace("/", File.separator)

override fun constructInPath(directoryName: String): String =
File(System.getProperty("user.dir")).resolve(
File("src${sep}test${sep}resources${sep}integration${sep}in$sep$directoryName")
).absolutePath.replace("/", File.separator)

private fun constructResultPath(directoryName: String): String =
File(System.getProperty("user.dir")).resolve(
File("src${sep}test${sep}resources${sep}integration${sep}in$sep${directoryName}_ddr")
).absolutePath.replace("/", File.separator)
}
105 changes: 105 additions & 0 deletions src/test/resources/integration/in/basic/app.xmir
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<program ms="152"
name="app"
source="/home/olesya/example/app.eo"
time="2022-10-19T09:33:18.115156299Z"
version="0.28.10">
<listing>[] &gt; cat
[] &gt; talk
QQ.io.stdout &gt; @
"Meow!"
[dir] &gt; move
QQ.io.stdout &gt; @
dir

[] &gt; dog
[] &gt; talk
QQ.io.stdout &gt; @
"Woof!"
[dir] &gt; move
QQ.io.stdout &gt; @
dir
[] &gt; smth
QQ.io.stdout &gt; @
"smth"

[x] &gt; some_object
x.talk &gt; heh
x.move "left" &gt; @

[x] &gt; other_object
x.talk &gt; @
x.smth &gt; hih

[] &gt; app
some_object dog &gt; so
so &gt; @
</listing>
<errors/>
<sheets/>
<objects>
<o abstract="" line="1" name="cat" pos="0">
<o abstract="" line="2" name="talk" pos="2">
<o base="QQ" line="3" pos="4"/>
<o base=".io" line="3" method="" pos="6"/>
<o base=".stdout" line="3" method="" name="@" pos="9">
<o base="string" data="string" line="4" pos="6">Meow!</o>
</o>
</o>
<o abstract="" line="5" name="move" pos="2">
<o line="5" name="dir" pos="3"/>
<o base="QQ" line="6" pos="4"/>
<o base=".io" line="6" method="" pos="6"/>
<o base=".stdout" line="6" method="" name="@" pos="9">
<o base="dir" line="7" pos="6"/>
</o>
</o>
</o>
<o abstract="" line="9" name="dog" pos="0">
<o abstract="" line="10" name="talk" pos="2">
<o base="QQ" line="11" pos="4"/>
<o base=".io" line="11" method="" pos="6"/>
<o base=".stdout" line="11" method="" name="@" pos="9">
<o base="string" data="string" line="12" pos="6">Woof!</o>
</o>
</o>
<o abstract="" line="13" name="move" pos="2">
<o line="13" name="dir" pos="3"/>
<o base="QQ" line="14" pos="4"/>
<o base=".io" line="14" method="" pos="6"/>
<o base=".stdout" line="14" method="" name="@" pos="9">
<o base="dir" line="15" pos="6"/>
</o>
</o>
<o abstract="" line="16" name="smth" pos="2">
<o base="QQ" line="17" pos="4"/>
<o base=".io" line="17" method="" pos="6"/>
<o base=".stdout" line="17" method="" name="@" pos="9">
<o base="string" data="string" line="18" pos="6">smth</o>
</o>
</o>
</o>
<o abstract="" line="20" name="some_object" pos="0">
<o line="20" name="x" pos="1"/>
<o base="x" line="21" pos="2"/>
<o base=".talk" line="21" method="" name="heh" pos="3"/>
<o base="x" line="22" pos="2"/>
<o base=".move" line="22" method="" name="@" pos="3">
<o base="string" data="string" line="22" pos="9">left</o>
</o>
</o>
<o abstract="" line="24" name="other_object" pos="0">
<o line="24" name="x" pos="1"/>
<o base="x" line="25" pos="2"/>
<o base=".talk" line="25" method="" name="@" pos="3"/>
<o base="x" line="26" pos="2"/>
<o base=".smth" line="26" method="" name="hih" pos="3"/>
</o>
<o abstract="" line="28" name="app" pos="0">
<o base="some_object" line="29" name="so" pos="2">
<o base="dog" line="29" pos="14"/>
</o>
<o base="so" line="30" name="@" pos="2"/>
</o>
</objects>
</program>
Loading

1 comment on commit 1858042

@0pdd
Copy link

@0pdd 0pdd commented on 1858042 Oct 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Puzzle 14-1df99bf7 discovered in src/main/kotlin/org/objectionary/aoi/transformer/XmirTransformer.kt) and submitted as #15. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

Please sign in to comment.