Skip to content
This repository has been archived by the owner on Aug 19, 2020. It is now read-only.

XML file editing with the groovy XML library is unwieldy in kotlin #225

Closed
JLLeitschuh opened this issue Jan 16, 2017 · 7 comments
Closed

Comments

@JLLeitschuh
Copy link
Contributor

Trying to do something like this:

http://mrhaki.blogspot.com/2016/03/gradle-goodness-add-spring-facet-to.html

idea {
    module {
        iml {
            withXml {
                // Get root of module as groovy.util.Node.
                def moduleRoot = it.asNode()
                 
                // Find if component with name 'FacetManager'
                // is already set.
                def facetManager = moduleRoot.component.find { component -> component.'@name' == 'FacetManager'}
                if (!facetManager) {
                    // Create new component with name 'FacetManager'
                    facetManager = moduleRoot.appendNode('component', [name: 'FacetManager'])
                }
                 
                // Find Spring facet it might already be there.
                def springFacet = facetManager.facet.find { facet -> facet.'@type' == 'Spring' && facet.'@name' == 'Spring' }
                if (!springFacet) {
                    // If not set create new facet node with name 'Spring'
                    // and type 'Spring' and apply a default configuration.
                    springFacet = facetManager.appendNode('facet', [type: 'Spring', name: 'Spring'])
                    springFacet.appendNode('configuration')
                }
            }
        }
    }
}

Is incredibly hard in kotlin because many of the methods rely on gradle's duck typing system.

@JLLeitschuh
Copy link
Contributor Author

Here's another example:

fun getEclipseFormatterSettings() : Collection<Pair<String, String>> {
    val eclipseFormatterSettingsXml = file("${rootProject.projectDir}/eclipse-formatter-settings.xml")
    val eclipseFormatter = XmlParser().parse(eclipseFormatterSettingsXml)
    return ((eclipseFormatter["profile"] as NodeList)[0] as Node).children().map {
        val node = it as Node
        node.attribute("id").toString() to node.attribute("value").toString()
    }
}

@eskatos
Copy link
Member

eskatos commented Jan 25, 2017

Hi @JLLeitschuh, thanks for the report.

XmlProvider exposes the underlying XML data in two useful flavors: groovy.util.Node and org.w3c.dom.Element. The former is meant to be used in Groovy build scripts and rely on Groovy's duck typing system like you said. The latter could be used with kotlinx.dom in a more Kotlin-way.

withXml {
  def moduleRoot = it.asElement() // instead of asNode()            
}

I didn't try that myself yet, I'll give it a shot soon, in the meantime I hope this helps.

@JLLeitschuh
Copy link
Contributor Author

I did end up using that to solve the problem. Good suggestion.

@eskatos
Copy link
Member

eskatos commented Jan 25, 2017

@JLLeitschuh would you mind sharing a snippet of the resulting build script?

@JLLeitschuh
Copy link
Contributor Author

JLLeitschuh commented Jan 25, 2017

configure<IdeaModel> {
    module.apply {
        generatedSourceDirs.apply {
            add(generatedDaoFile)
            add(generatedJobFile)
        }
        iml.apply {
            withXml {
                val moduleRoot = it.asElement()
                val doc = moduleRoot.ownerDocument

                fun NodeList.asElementList() = asList().filterIsInstance<Element>()

                val facetManager = moduleRoot
                    .getElementsByTagName("component")
                    .asElementList()
                    .singleOrNull { it.getAttribute("name") == "FacetManager" }
                    ?: moduleRoot
                    .appendChild(doc.createElement("component").apply {
                        setAttribute("name", "FacetManager")
                    }) as Element

                // Add spring facet
                facetManager
                    .getElementsByTagName("facet")
                    .asElementList()
                    .singleOrNull { it.getAttribute("name") == "Spring" && it.getAttribute("type") == "Spring" }
                    ?: facetManager
                    .appendChild(doc.createElement("facet").apply {
                        setAttribute("name", "Spring")
                        setAttribute("type", "Spring")
                        appendChild(doc.createElement("configuration"))
                    })

                // Add AspectJ facet
                facetManager
                    .getElementsByTagName("facet")
                    .asElementList()
                    .singleOrNull { it.getAttribute("name") == "AspectJ" && it.getAttribute("type") == "AspectJ" }
                    ?: facetManager
                    .appendChild(doc.createElement("facet").apply {
                        setAttribute("name", "AspectJ")
                        setAttribute("type", "AspectJ")
                        appendChild(doc.createElement("configuration").apply {
                            appendChild(doc.createElement("option").apply {
                                setAttribute("name", "aspectPath")
                                appendChild(doc.createElement("projectLibrary").apply {
                                    appendChild(doc.createElement("option").apply {
                                        setAttribute("name", "name")
                                        setAttribute("value", "Gradle: org.springframework:spring-aspects:$springVersion")
                                    })
                                })
                            })
                        })
                    })
            }
        }
    }
}

// Helper Utilities
fun NodeList.asList() = (0..length).map { item(it) }

@baron1405
Copy link

I just started using kotlinx.dom and it results in much more succinct code. Great project and it is from JetBrains!

@eskatos
Copy link
Member

eskatos commented Jan 17, 2018

Closing as answered.

@eskatos eskatos closed this as completed Jan 17, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants