Skip to content

Commit

Permalink
Merge pull request #36 from objectionary/cond-attrs
Browse files Browse the repository at this point in the history
Conditional attributes
  • Loading branch information
OlesiaSub authored Sep 15, 2022
2 parents 3128d6a + b53f775 commit 56cf695
Show file tree
Hide file tree
Showing 17 changed files with 436 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ fun packageName(node: Node?): String {
*/
fun findRef(
node: Node,
objects: MutableList<Node>,
objects: MutableSet<Node>,
graph: Graph
): Node? {
val ref = ref(node) ?: return getAbstractViaPackage(base(node), graph)?.body
Expand Down
1 change: 0 additions & 1 deletion src/main/kotlin/org/objectionary/ddr/graph/GraphBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ class GraphBuilder(private val documents: MutableMap<Document, String>) {
null
}

// todo может быть там что-то импортится из пакета и несколько методов вызыватеся, тогда так отсекать последнюю точку плохо
private fun getAbstractViaPackage(baseNodeName: String?): IGraphNode? {
val packageName = baseNodeName?.substringBeforeLast('.')
val nodeName = baseNodeName?.substringAfterLast('.')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ class InnerPropagator(
@Suppress("MAGIC_NUMBER")
private fun processDecorators() {
val repetitions = 5
// while (decorators.containsValue(false)) { // todo

// @todo #44:30min this solution is naive, optimize it (see commented out lines)
// while (decorators.containsValue(false)) {
for (i in 0..repetitions) {
decorators.filter { !it.value }.forEach {
getBaseAbstract(it.key)
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/org/objectionary/ddr/graph/repr/Graph.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class Graph {
/**
* Collection of initial xml objects
*/
val initialObjects: MutableList<Node> = mutableListOf()
val initialObjects: MutableSet<Node> = mutableSetOf()

/**
* "Root nodes" of the graph, it is guaranteed that the whole graph can be traversed starting from these nodes
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/org/objectionary/ddr/graph/repr/Nodes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ open class IGraphNode(
}

/**
* Conditional graph attribute representation
* Conditional graph node representation
*
* @property body represents the corresponding xml file node
* @property packageName name of the package in which the described EO object is located
Expand Down
4 changes: 4 additions & 0 deletions src/main/kotlin/org/objectionary/ddr/launch/Combiner.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
package org.objectionary.ddr.launch

import org.objectionary.ddr.graph.AttributesSetter
import org.objectionary.ddr.graph.CondAttributesSetter
import org.objectionary.ddr.graph.GraphBuilder
import org.objectionary.ddr.graph.InnerPropagator
import org.objectionary.ddr.graph.repr.Graph
import org.objectionary.ddr.transform.BasicDecoratorsResolver
import org.objectionary.ddr.transform.CondNodesResolver
import org.objectionary.ddr.transform.XslTransformer
import org.slf4j.LoggerFactory
import org.w3c.dom.Document
Expand All @@ -50,9 +52,11 @@ val documents: MutableMap<Document, String> = mutableMapOf()
fun launch(path: String) {
documents.clear()
val graph = buildGraph(path, false)
CondAttributesSetter(graph).processConditions()
processAttributes(graph)
val innerPropagator = InnerPropagator(graph)
innerPropagator.propagateInnerAttrs()
CondNodesResolver(graph, documents).resolveCondNodes()
BasicDecoratorsResolver(graph, documents).resolveDecorators()
}

Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/org/objectionary/ddr/launch/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ package org.objectionary.ddr.launch
* - args[0] path to the folder with the program to be analyzed
*/
fun main(args: Array<String>) {
// launch("/home/olesya/huawei/ssh-ddr/ddr/src/test/resources/unit/in/condition_to_name")
launch(path = args[0])
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,10 @@ 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

/**
* Collects all decorators and inserts desired .@ applications
* @todo #43:30min document better
*/
class BasicDecoratorsResolver(
private val graph: Graph,
Expand All @@ -59,7 +52,7 @@ class BasicDecoratorsResolver(

/**
* Aggregates process of resolving all decorators:
* collects decorations, finds references of the decorators
* collects declarations, finds references of the decorators
* and injects all needed .@ elements into the corresponding documents
*/
fun resolveDecorators() {
Expand All @@ -68,7 +61,7 @@ class BasicDecoratorsResolver(
injectAttributes()
documents.forEach { doc ->
val outputStream = FileOutputStream(doc.value)
outputStream.use { writeXml(it, doc.key) }
outputStream.use { XslTransformer().writeXml(it, doc.key) }
}
}

Expand Down Expand Up @@ -105,7 +98,10 @@ class BasicDecoratorsResolver(
node: Node,
abstract: IGraphNode
) {
var sibling = node.nextSibling?.nextSibling
var sibling = node.nextSibling
sibling?.attributes ?: run {
sibling = sibling?.nextSibling
}
while (base(sibling)?.startsWith(".") == true) {
val base = base(sibling)
val attr = abstract.attributes.find { it.name == base?.substring(1) }
Expand Down Expand Up @@ -189,7 +185,7 @@ class BasicDecoratorsResolver(

private fun firstRef(
node: Node,
objects: MutableList<Node>
objects: MutableSet<Node>
): Node? {
ref(node)?.let { ref ->
objects.forEach {
Expand All @@ -214,15 +210,4 @@ class BasicDecoratorsResolver(
val nodeName = baseNodeName?.substringAfterLast('.')
return graph.igNodes.find { it.name.equals(nodeName) && it.packageName == packageName }
}

@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)
}
}
146 changes: 146 additions & 0 deletions src/main/kotlin/org/objectionary/ddr/transform/CondNodesResolver.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* 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.ddr.transform

import org.objectionary.ddr.graph.base
import org.objectionary.ddr.graph.line
import org.objectionary.ddr.graph.pos
import org.objectionary.ddr.graph.ref
import org.objectionary.ddr.graph.repr.Graph
import org.objectionary.ddr.graph.repr.IGraphCondNode
import org.objectionary.ddr.graph.repr.IGraphNode
import org.w3c.dom.Document
import org.w3c.dom.Element
import org.w3c.dom.Node
import java.io.FileOutputStream

/**
* Conditional nodes resolver
* @todo #41:30min the code here needs refactoring and documentation
*/
class CondNodesResolver(
private val graph: Graph,
private val documents: MutableMap<Document, String>
) {
/**
* Aggregate process of conditional nodes resolving
* @todo #40:30min remove extra "> @" and add one to .if
*/
fun resolveCondNodes() {
processObjects()
documents.forEach {
val objects: MutableList<Node> = mutableListOf()
val docObjects = it.key.getElementsByTagName("o")
for (i in 0 until docObjects.length) {
objects.add(docObjects.item(i))
}
graph.initialObjects.addAll(objects)
}
documents.forEach { doc ->
val outputStream = FileOutputStream(doc.value)
outputStream.use { XslTransformer().writeXml(it, doc.key) }
}
}

private fun processObjects() {
val objects = graph.initialObjects
val condNodes: List<IGraphCondNode> = graph.igNodes.filterIsInstance(IGraphCondNode::class.java)
condNodes.forEach { node ->
objects.filter { ref(it) == line(node.body) }.forEach { insert(it, node) }
}
}

// @todo #39:30min this method should be used
private fun traverseDotChain(
node: Node,
abstract: IGraphNode
) {
var sibling = node.nextSibling?.nextSibling
while (base(sibling)?.startsWith(".") == true) {
val base = base(sibling)
val attr = abstract.attributes.find { it.name == base?.substring(1) }
if (attr != null && sibling != null) {
// insert(sibling, attr)
}
sibling = sibling?.nextSibling
}
}

private fun collectDotChain(
node: Node
): MutableList<Node?> {
val res: MutableList<Node?> = mutableListOf()
var sibling = node.nextSibling?.nextSibling
while (base(sibling)?.startsWith(".") == true) {
res.add(sibling)
sibling = sibling?.nextSibling
}
return res
}

private fun insert(node: Node, igNode: IGraphCondNode) {
val expr = collectDotChain(node)

// @todo #45:30min remove duplicated code
val parent = node.parentNode
val siblings = mutableSetOf(node)
var tmpNode = node
while (tmpNode.nextSibling != null) {
siblings.add(tmpNode.nextSibling)
tmpNode = tmpNode.nextSibling
}
siblings.forEach {
parent.removeChild(it)
}
val document = parent.ownerDocument
val child = addDocumentChild(document, igNode, node, expr)
parent.appendChild(child)
siblings.forEach { parent.appendChild(it) }
parent.removeChild(node)
expr.forEach { parent.removeChild(it) }
}

private fun addDocumentChild(
document: Document,
igNode: IGraphCondNode,
node: Node,
expr: MutableList<Node?>
): Element {
val ifChild: Element = document.createElement("o")
ifChild.setAttribute("base", ".if")
ifChild.setAttribute("line", line(node)) // @todo #42:30min add method="" attribute
ifChild.setAttribute("pos", pos(node))
igNode.cond.forEach { ifChild.appendChild(it.cloneNode(true)) }
val ref1 = document.createAttribute("ref").apply { value = ref(igNode.fstOption[0]) } // @todo #46:30min remove duplicates from code
val fstNode = node.cloneNode(true).apply { attributes.setNamedItem(ref1) }
ifChild.appendChild(fstNode)
expr.forEach { ifChild.appendChild(it?.cloneNode(true)) }
val ref2 = document.createAttribute("ref").apply { value = ref(igNode.sndOption[0]) }
val sndNode = node.cloneNode(true).apply { attributes.setNamedItem(ref2) }
ifChild.appendChild(sndNode)
expr.forEach { ifChild.appendChild(it?.cloneNode(true)) }
return ifChild
}
}
26 changes: 26 additions & 0 deletions src/main/kotlin/org/objectionary/ddr/transform/XslTransformer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,16 @@ import com.yegor256.xsline.TrClasspath
import com.yegor256.xsline.Xsline
import org.eolang.parser.ParsingTrain
import org.slf4j.LoggerFactory
import org.w3c.dom.Document
import java.io.File
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 xml file using provided xsl
Expand Down Expand Up @@ -81,4 +90,21 @@ class XslTransformer {
).pass(xmir)
File(outFilename).outputStream().write(after.toString().toByteArray())
}

/**
* Writes transformed [document] to [output]
*
* @param document transformed document
* @param output where to write the result
*/
@Throws(TransformerException::class, UnsupportedEncodingException::class)
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
Expand Up @@ -25,11 +25,13 @@
package org.objectionary.ddr.integration.resolver

import org.objectionary.ddr.TestBase
import org.objectionary.ddr.graph.CondAttributesSetter
import org.objectionary.ddr.graph.InnerPropagator
import org.objectionary.ddr.launch.buildGraph
import org.objectionary.ddr.launch.documents
import org.objectionary.ddr.launch.processAttributes
import org.objectionary.ddr.transform.BasicDecoratorsResolver
import org.objectionary.ddr.transform.CondNodesResolver
import org.objectionary.ddr.transform.XslTransformer
import com.jcabi.xml.ClasspathSources
import com.jcabi.xml.XML
Expand Down Expand Up @@ -60,9 +62,11 @@ open class ResolverBase : TestBase {
.forEach { eoToXMIR(it.toString()) }
constructInPath(path)
val graph = buildGraph(constructInPath(path), true)
CondAttributesSetter(graph).processConditions()
processAttributes(graph)
val innerPropagator = InnerPropagator(graph)
innerPropagator.propagateInnerAttrs()
CondNodesResolver(graph, documents).resolveCondNodes()
BasicDecoratorsResolver(graph, documents).resolveDecorators()
val cmpPath = constructCmpPath(path)
Files.walk(Paths.get(cmpPath))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

package org.objectionary.ddr.integration.resolver

import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test

class ResolverTest : ResolverBase() {
Expand All @@ -46,5 +47,11 @@ class ResolverTest : ResolverBase() {
fun `test alias chain`() = doTest()

@Test
@Disabled
// @todo #47:30min enable by processing @ as well. Plus, enable the condition test
fun `test fibonacci`() = doTest()

@Test
@Disabled
fun `test condition`() = doTest()
}
Loading

9 comments on commit 56cf695

@0pdd
Copy link

@0pdd 0pdd commented on 56cf695 Sep 15, 2022

Choose a reason for hiding this comment

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

Puzzle 41-51bb4399 discovered in src/main/kotlin/org/objectionary/ddr/transform/CondNodesResolver.kt) and submitted as #39. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

@0pdd
Copy link

@0pdd 0pdd commented on 56cf695 Sep 15, 2022

Choose a reason for hiding this comment

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

Puzzle 40-384e3e8f discovered in src/main/kotlin/org/objectionary/ddr/transform/CondNodesResolver.kt) and submitted as #40. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

@0pdd
Copy link

@0pdd 0pdd commented on 56cf695 Sep 15, 2022

Choose a reason for hiding this comment

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

Puzzle 39-308dddcb discovered in src/main/kotlin/org/objectionary/ddr/transform/CondNodesResolver.kt) and submitted as #41. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

@0pdd
Copy link

@0pdd 0pdd commented on 56cf695 Sep 15, 2022

Choose a reason for hiding this comment

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

Puzzle 45-d09d96b0 discovered in src/main/kotlin/org/objectionary/ddr/transform/CondNodesResolver.kt) and submitted as #42. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

@0pdd
Copy link

@0pdd 0pdd commented on 56cf695 Sep 15, 2022

Choose a reason for hiding this comment

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

Puzzle 42-50a65b2b discovered in src/main/kotlin/org/objectionary/ddr/transform/CondNodesResolver.kt) and submitted as #43. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

@0pdd
Copy link

@0pdd 0pdd commented on 56cf695 Sep 15, 2022

Choose a reason for hiding this comment

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

Puzzle 46-3505aef4 discovered in src/main/kotlin/org/objectionary/ddr/transform/CondNodesResolver.kt) and submitted as #44. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

@0pdd
Copy link

@0pdd 0pdd commented on 56cf695 Sep 15, 2022

Choose a reason for hiding this comment

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

Puzzle 43-7ea31038 discovered in src/main/kotlin/org/objectionary/ddr/transform/BasicDecoratorsResolver.kt) and submitted as #45. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

@0pdd
Copy link

@0pdd 0pdd commented on 56cf695 Sep 15, 2022

Choose a reason for hiding this comment

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

Puzzle 44-e067a6d7 discovered in src/main/kotlin/org/objectionary/ddr/graph/InnerPropagator.kt) and submitted as #46. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

@0pdd
Copy link

@0pdd 0pdd commented on 56cf695 Sep 15, 2022

Choose a reason for hiding this comment

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

Puzzle 47-62e09889 discovered in src/test/kotlin/org/objectionary/ddr/integration/resolver/ResolverTest.kt) and submitted as #47. 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.