From 1d0ce3c88317110c8791629a7f8ef2afafb343eb Mon Sep 17 00:00:00 2001 From: Jason Blackwell Date: Sun, 22 Oct 2023 21:38:16 -0400 Subject: [PATCH] =?UTF-8?q?feat:=20adding=20addElements,=20addElementsAfte?= =?UTF-8?q?r,=20addElementsBefore,=20replac=E2=80=A6=20(#60)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: adding addElements, addElementsAfter, addElementsBefore, replaceElement, and replaceElement. adding ktlint * chore: bumping version to 1.9.1 and adding release notes --- .editorconfig | 2 + README.md | 8 + build.gradle.kts | 15 +- kotlin-xml-builder/build.gradle.kts | 1 + .../org/redundent/kotlin/xml/Attribute.kt | 7 +- .../org/redundent/kotlin/xml/CDATAElement.kt | 12 +- .../org/redundent/kotlin/xml/Comment.kt | 2 +- .../org/redundent/kotlin/xml/Doctype.kt | 39 +- .../org/redundent/kotlin/xml/Element.kt | 2 +- .../org/redundent/kotlin/xml/Namespace.kt | 3 +- .../kotlin/org/redundent/kotlin/xml/Node.kt | 501 ++++++++++++------ .../org/redundent/kotlin/xml/PrintOptions.kt | 2 +- .../xml/ProcessingInstructionElement.kt | 11 +- .../kotlin/xml/{sitemap.kt => Sitemap.kt} | 21 +- .../kotlin/org/redundent/kotlin/xml/Unsafe.kt | 2 +- .../kotlin/xml/{utils.kt => Utils.kt} | 4 +- .../org/redundent/kotlin/xml/XmlBuilder.kt | 47 +- .../org/redundent/kotlin/xml/XmlType.kt | 2 +- .../org/redundent/kotlin/xml/XmlVersion.kt | 2 +- .../redundent/kotlin/xml/CDATAElementTest.kt | 2 +- .../org/redundent/kotlin/xml/CommentTest.kt | 2 +- .../org/redundent/kotlin/xml/NodeTest.kt | 123 ++++- .../redundent/kotlin/xml/OrderedNodesTest.kt | 2 +- .../xml/ProcessingInstructionElementTest.kt | 2 +- .../{XmlBuilderTestBase.kt => TestBase.kt} | 6 +- .../redundent/kotlin/xml/TextElementTest.kt | 3 +- .../org/redundent/kotlin/xml/UtilsKtTest.kt | 2 +- .../redundent/kotlin/xml/XmlBuilderTest.kt | 83 +-- .../org/redundent/kotlin/xml/sitemapTest.kt | 14 +- .../NodeTest/addElementsAfter.xml | 9 + .../NodeTest/addElementsBefore.xml | 9 + .../{addNode.xml => addElement.xml} | 0 .../{addNodeAfter.xml => addElementAfter.xml} | 0 ...Child.xml => addElementAfterLastChild.xml} | 0 ...addNodeBefore.xml => addElementBefore.xml} | 0 .../{removeNode.xml => removeElement.xml} | 0 .../{replaceNode.xml => replaceElement.xml} | 0 kotlin-xml-dsl-generator/build.gradle.kts | 1 + .../redundent/kotlin/xml/gen/DslGenerator.kt | 20 +- .../redundent/kotlin/xml/gen/SchemaOutline.kt | 2 +- .../redundent/kotlin/xml/gen/writer/Code.kt | 2 +- .../kotlin/xml/gen/writer/XmlAttribute.kt | 8 +- .../kotlin/xml/gen/writer/XmlClass.kt | 29 +- .../kotlin/xml/gen/writer/XmlElement.kt | 25 +- .../kotlin/xml/gen/writer/XmlEnum.kt | 4 +- .../kotlin/xml/gen/AbstractGenTest.kt | 6 +- .../{SimpleSchemGen.kt => SimpleSchemaGen.kt} | 4 +- .../src/test/resources/code/choice.kt | 6 +- .../test/resources/code/duplicate-names.kt | 2 +- .../src/test/resources/code/nested.kt | 4 +- .../src/test/resources/code/sitemap.kt | 2 +- settings.gradle.kts | 1 - 52 files changed, 719 insertions(+), 337 deletions(-) create mode 100644 .editorconfig rename kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/{sitemap.kt => Sitemap.kt} (72%) rename kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/{utils.kt => Utils.kt} (93%) rename kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/{XmlBuilderTestBase.kt => TestBase.kt} (96%) create mode 100644 kotlin-xml-builder/src/test/resources/test-results/NodeTest/addElementsAfter.xml create mode 100644 kotlin-xml-builder/src/test/resources/test-results/NodeTest/addElementsBefore.xml rename kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/{addNode.xml => addElement.xml} (100%) rename kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/{addNodeAfter.xml => addElementAfter.xml} (100%) rename kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/{addNodeAfterLastChild.xml => addElementAfterLastChild.xml} (100%) rename kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/{addNodeBefore.xml => addElementBefore.xml} (100%) rename kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/{removeNode.xml => removeElement.xml} (100%) rename kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/{replaceNode.xml => replaceElement.xml} (100%) rename kotlin-xml-dsl-generator/src/test/kotlin/org/redundent/kotlin/xml/gen/{SimpleSchemGen.kt => SimpleSchemaGen.kt} (93%) diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..2b2592b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,2 @@ +[*.{kt,kts}] +indent_style = tab \ No newline at end of file diff --git a/README.md b/README.md index 9c3a6dc..584d64f 100644 --- a/README.md +++ b/README.md @@ -276,6 +276,14 @@ It includes many more features for consuming documents. Release Notes ============= +Version 1.9.1 +- +* Adding `addElement`, `addElements`, `addElementsBefore`, `addElementsAfter`, `removeElement`, +`removeElements`, and `replaceElement` to Node.\ +Thanks to [@csmile2](https://github.com/csmile2) for requesting this! +* Deprecating `addNode`, `addNodeBefore`, `addNodeAfter`, `removeNode`, and `replaceNode` in favor of Element methods. +* Adding ktlint checks + Version 1.9.0 - * Adding `unsafe` and `unsafeText` methods to allow for unescaped values in elements and attributes.\ diff --git a/build.gradle.kts b/build.gradle.kts index 87e9346..7d631bf 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,13 +2,14 @@ plugins { kotlin("jvm") version "1.6.20" apply false id("com.bmuschko.nexus") version "2.3.1" apply false id("io.github.gradle-nexus.publish-plugin") version "2.0.0-rc-1" + id("org.jlleitschuh.gradle.ktlint") version "11.6.1" } extra["kotlinVersion"] = "1.6.20" allprojects { group = "org.redundent" - version = "1.9.0" + version = "1.9.1" repositories { mavenCentral() @@ -25,10 +26,12 @@ subprojects { afterEvaluate { configure { publications.withType { - artifact(tasks.register("${name}JavadocJar", Jar::class) { - archiveClassifier.set("javadoc") - archiveAppendix.set(this@withType.name) - }) + artifact( + tasks.register("${name}JavadocJar", Jar::class) { + archiveClassifier.set("javadoc") + archiveAppendix.set(this@withType.name) + } + ) pom { name.set("Kotlin XML Builder") @@ -61,4 +64,4 @@ subprojects { } } } -} \ No newline at end of file +} diff --git a/kotlin-xml-builder/build.gradle.kts b/kotlin-xml-builder/build.gradle.kts index 9c4dced..9658d75 100644 --- a/kotlin-xml-builder/build.gradle.kts +++ b/kotlin-xml-builder/build.gradle.kts @@ -2,6 +2,7 @@ plugins { kotlin("jvm") `maven-publish` signing + id("org.jlleitschuh.gradle.ktlint") } val kotlinVersion: String by rootProject.extra diff --git a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Attribute.kt b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Attribute.kt index 5784865..87de2bd 100644 --- a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Attribute.kt +++ b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Attribute.kt @@ -1,6 +1,7 @@ package org.redundent.kotlin.xml data class Attribute @JvmOverloads constructor( - val name: String, - val value: Any, - val namespace: Namespace? = null) \ No newline at end of file + val name: String, + val value: Any, + val namespace: Namespace? = null +) diff --git a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/CDATAElement.kt b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/CDATAElement.kt index c825ca8..9514450 100644 --- a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/CDATAElement.kt +++ b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/CDATAElement.kt @@ -11,8 +11,8 @@ class CDATAElement internal constructor(text: String) : TextElement(text) { val cdataEnd = "]]>" val cdataStart = "") + // split cdataEnd into two pieces so XML parser doesn't recognize it + .replace(cdataEnd, "]]$cdataEnd$cdataStart>") } return "" @@ -23,7 +23,7 @@ class CDATAElement internal constructor(text: String) : TextElement(text) { // Need to use javaClass here to avoid a normal TextElement and a CDATAElement having the same hashCode if they have // the same text override fun hashCode(): Int = HashCodeBuilder() - .appendSuper(super.hashCode()) - .append(javaClass.hashCode()) - .toHashCode() -} \ No newline at end of file + .appendSuper(super.hashCode()) + .append(javaClass.hashCode()) + .toHashCode() +} diff --git a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Comment.kt b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Comment.kt index aae1038..7c78000 100644 --- a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Comment.kt +++ b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Comment.kt @@ -14,4 +14,4 @@ class Comment internal constructor(val text: String) : Element { override fun equals(other: Any?): Boolean = other is Comment && other.text == text override fun hashCode(): Int = text.hashCode() -} \ No newline at end of file +} diff --git a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Doctype.kt b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Doctype.kt index 5f5552b..2707dbc 100644 --- a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Doctype.kt +++ b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Doctype.kt @@ -1,27 +1,28 @@ package org.redundent.kotlin.xml class Doctype @JvmOverloads constructor( - private val name: String, - private val systemId: String? = null, - private val publicId: String? = null) : Element { + private val name: String, + private val systemId: String? = null, + private val publicId: String? = null +) : Element { - override fun render(builder: Appendable, indent: String, printOptions: PrintOptions) { - builder.append("") - } -} \ No newline at end of file + builder.appendLine(">") + } +} diff --git a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Element.kt b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Element.kt index 65931d8..a680a33 100644 --- a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Element.kt +++ b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Element.kt @@ -9,4 +9,4 @@ interface Element { * This method handles creating the xml. Used internally */ fun render(builder: Appendable, indent: String, printOptions: PrintOptions) -} \ No newline at end of file +} diff --git a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Namespace.kt b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Namespace.kt index 2c0ff48..57afcf1 100644 --- a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Namespace.kt +++ b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Namespace.kt @@ -11,7 +11,8 @@ data class Namespace( /** * The value/uri/url of the namespace */ - val value: String) { + val value: String +) { constructor(value: String) : this("", value) diff --git a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Node.kt b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Node.kt index ff8fbfb..bad24ba 100644 --- a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Node.kt +++ b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Node.kt @@ -2,9 +2,9 @@ package org.redundent.kotlin.xml import org.apache.commons.lang3.builder.EqualsBuilder import org.apache.commons.lang3.builder.HashCodeBuilder -import java.util.ArrayList -import java.util.NoSuchElementException +import java.util.* import kotlin.collections.LinkedHashMap +import kotlin.collections.LinkedHashSet /** * Base type for all elements. This is what handles pretty much all the rendering and building. @@ -27,7 +27,6 @@ open class Node(val nodeName: String) : Element { return@lazy null } - @Suppress("NO_REFLECTION_IN_CLASS_PATH") // Checked for reflection class above val xmlTypeAnnotation = this::class.annotations.firstOrNull { it is XmlType } as? XmlType ?: return@lazy null val childOrder = xmlTypeAnnotation.childOrder @@ -104,9 +103,7 @@ open class Node(val nodeName: String) : Element { } _children.add(tag) - if (tag is Node) { - tag.parent = this - } + setParentIfNode(tag, this) return tag } @@ -114,9 +111,9 @@ open class Node(val nodeName: String) : Element { /** * Allows for easy access of this node's attributes * - * - * val attr = element["key"] - * + * ``` + * val attr = element["key"] + * ``` */ operator fun get(attributeName: String): T? { val value = _attributes[attributeName] @@ -128,9 +125,9 @@ open class Node(val nodeName: String) : Element { * Allows for easy access of adding/updating this node's attributes. Setting the value of an attribute to "null" * will remove the attribute . * - * - * element["key"] = "value" - * + * ``` + * element["key"] = "value" + * ``` */ operator fun set(attributeName: String, value: Any?) { if (value == null) { @@ -154,11 +151,12 @@ open class Node(val nodeName: String) : Element { builder.append("$indent<$nodeName${renderNamespaces()}${renderAttributes(printOptions)}") if (!isEmptyOrSingleEmptyTextElement()) { - if (printOptions.pretty && printOptions.singleLineTextElements - && _children.size == 1 && _children[0] is TextElement) { - builder.append(">") + if (printOptions.pretty && printOptions.singleLineTextElements && + _children.size == 1 && _children[0] is TextElement + ) { + builder.append(">") (_children[0] as TextElement).renderSingleLine(builder, printOptions) - builder.append("$lineEnding") + builder.append("$lineEnding") } else { builder.append(">$lineEnding") for (c in sortedChildren()) { @@ -184,21 +182,22 @@ open class Node(val nodeName: String) : Element { return false } - private fun getEmptyTagClosing(printOptions: PrintOptions): String = if (printOptions.useSelfClosingTags) + private fun getEmptyTagClosing(printOptions: PrintOptions): String = if (printOptions.useSelfClosingTags) { "/>" - else + } else { ">" + } private fun sortedChildren(): List { return if (childOrderMap == null) { _children } else { - _children.sortedWith(Comparator { a, b -> + _children.sortedWith { a, b -> val indexA = if (a is Node) childOrderMap!![a.nodeName] else 0 val indexB = if (b is Node) childOrderMap!![b.nodeName] else 0 compareValues(indexA, indexB) - }) + } } } @@ -225,11 +224,22 @@ open class Node(val nodeName: String) : Element { return _attributes.entries.joinToString(" ", prefix = " ") { val value = it.value - "${it.key}=\"${if (value is Unsafe) value.value?.toString() else escapeValue(it.value, printOptions.xmlVersion, printOptions.useCharacterReference)}\"" + val text = if (value is Unsafe) { + value.value?.toString() + } else { + escapeValue( + it.value, + printOptions.xmlVersion, + printOptions.useCharacterReference + ) + } + + "${it.key}=\"$text\"" } } - private fun getIndent(printOptions: PrintOptions, indent: String): String = if (!printOptions.pretty) "" else "$indent${printOptions.indent}" + private fun getIndent(printOptions: PrintOptions, indent: String): String = + if (!printOptions.pretty) { "" } else { "$indent${printOptions.indent}" } /** * Get the xml representation of this object with prettyFormat = true @@ -243,8 +253,8 @@ open class Node(val nodeName: String) : Element { */ fun toString(prettyFormat: Boolean): String = toString(PrintOptions(pretty = prettyFormat)) - fun toString(printOptions: PrintOptions): String - = StringBuilder().also { writeTo(it, printOptions) }.toString().trim() + fun toString(printOptions: PrintOptions): String = + StringBuilder().also { writeTo(it, printOptions) }.toString().trim() fun writeTo(appendable: Appendable, printOptions: PrintOptions = PrintOptions()) { val lineEnding = getLineEnding(printOptions) @@ -283,12 +293,12 @@ open class Node(val nodeName: String) : Element { } /** - * Adds an xml comment to the document. - * - * comment("my comment") - * + * Adds an XML comment to the document. + * ``` + * comment("my comment") + * ``` * - * @param text The text of the comment. This text will be rendenered unescaped except for replace "--" with "--"] + * @param text The text of the comment. This text will be rendered unescaped except for replace "--" with "--" */ fun comment(text: String) { _children.add(Comment(text)) @@ -296,11 +306,11 @@ open class Node(val nodeName: String) : Element { /** * Adds a basic element with the specific name to the parent. - * - * element("url") { - * ... - * } - * + * ``` + * element("url") { + * ... + * } + * ``` * * @param name The name of the element. * @param namespace Optional namespace object to use to build the name of the attribute. @@ -317,9 +327,9 @@ open class Node(val nodeName: String) : Element { /** * Adds a basic element with the specific name and value to the parent. This cannot be used for complex elements. - * - * element("url", "https://google.com") - * + * ``` + * element("url", "https://google.com") + * ``` * * @param name The name of the element. * @param value The inner text of the element @@ -339,9 +349,9 @@ open class Node(val nodeName: String) : Element { /** * Adds a basic element with the specific name and value to the parent. This cannot be used for complex elements. - * - * "url"("https://google.com") - * + * ``` + * "url"("https://google.com") + * ``` * * @receiver The name of the element. * @param value The inner text of the element @@ -352,14 +362,14 @@ open class Node(val nodeName: String) : Element { /** * Adds a basic element with the specific name to the parent. This method * allows you to specify optional attributes and content - * - * "url"("key" to "value") { - * ... - * } - * + * ``` + * "url"("key" to "value") { + * ... + * } + * ``` * * @receiver The name of the element. - * @param attributes Any attributes to add to this element. Can be omited. + * @param attributes Any attributes to add to this element. Can be omitted. * @param init The block that defines the content of the element. */ operator fun String.invoke(vararg attributes: Pair, init: (Node.() -> Unit)? = null): Node { @@ -369,29 +379,33 @@ open class Node(val nodeName: String) : Element { /** * Adds a basic element with the specific name to the parent. This method * allows you to specify the namespace of the element as well as optional attributes and content - * - * "url"(ns, "key" to "value") { - * ... - * } - * + * ``` + * "url"(ns, "key" to "value") { + * ... + * } + * ``` * * @receiver The name of the element. * @param namespace Namespace object to use to build the name of the attribute. - * @param attributes Any attributes to add to this element. Can be omited. + * @param attributes Any attributes to add to this element. Can be omitted. * @param init The block that defines the content of the element. */ - operator fun String.invoke(namespace: Namespace, vararg attributes: Pair, init: (Node.() -> Unit)? = null): Node { + operator fun String.invoke( + namespace: Namespace, + vararg attributes: Pair, + init: (Node.() -> Unit)? = null + ): Node { return addElement(this, attributes.map { Attribute(it.first, it.second) }.toTypedArray(), namespace, init) } /** * Adds a basic element with the specific name to the parent. This method * allows you to specify the namespace of the element - * - * "url"(ns) { - * ... - * } - * + * ``` + * "url"(ns) { + * ... + * } + * ``` * * @receiver The name of the element. * @param namespace Namespace object to use to build the name of the attribute. @@ -404,22 +418,31 @@ open class Node(val nodeName: String) : Element { /** * Adds a basic element with the specific name to the parent. This method * allows you to specify namespace of the element as well as optional attributes (with namespaces) and content - * - * "url"(ns, Attribute("key", "value", otherNs)) { - * ... - * } - * + * ``` + * "url"(ns, Attribute("key", "value", otherNs)) { + * ... + * } + * ``` * * @receiver The name of the element. * @param namespace Namespace object to use to build the name of the attribute. - * @param attributes Any attributes to add to this element. Can be omited. + * @param attributes Any attributes to add to this element. Can be omitted. * @param init The block that defines the content of the element. */ - operator fun String.invoke(namespace: Namespace, vararg attributes: Attribute, init: (Node.() -> Unit)? = null): Node { + operator fun String.invoke( + namespace: Namespace, + vararg attributes: Attribute, + init: (Node.() -> Unit)? = null + ): Node { return addElement(this, attributes, namespace, init) } - private fun addElement(name: String, attributes: Array, namespace: Namespace?, init: (Node.() -> Unit)?): Node { + private fun addElement( + name: String, + attributes: Array, + namespace: Namespace?, + init: (Node.() -> Unit)? + ): Node { val e = element(name, namespace) { attributes(*attributes) } @@ -441,16 +464,16 @@ open class Node(val nodeName: String) : Element { /** * Adds an attribute to the current element - * - * "url" { - * attribute("key", "value") - * } - * + * ``` + * "url" { + * attribute("key", "value") + * } + * ``` * - * @param name The name of the attribute. This is currenly no validation against the name. + * @param name The name of the attribute. This is currently no validation against the name. * @param value The attribute value. * @param namespace Optional namespace object to use to build the name of the attribute. Note this does NOT declare - * the namespace. It simple uses it to build the attribute name. + * the namespace. It simply uses it to build the attribute name. */ fun attribute(name: String, value: Any, namespace: Namespace? = null) { if (namespace != null) { @@ -463,14 +486,14 @@ open class Node(val nodeName: String) : Element { * Adds a set of attributes to the current element. * @see [attribute] * - * - * "url" { - * attributes( - * "key" to "value", - * "id" to "1" - * ) - * } - * + * ``` + * "url" { + * attributes( + * "key" to "value", + * "id" to "1" + * ) + * } + * ``` * * @param attrs Collection of the attributes to apply to this element. */ @@ -482,14 +505,14 @@ open class Node(val nodeName: String) : Element { * Adds a set of attributes to the current element. * @see [attribute] * - * - * "url" { - * attributes( - * Attribute("key", "value", namespace), - * Attribute("id", "1", namespace) - * ) - * } - * + * ``` + * "url" { + * attributes( + * Attribute("key", "value", namespace), + * Attribute("id", "1", namespace) + * ) + * } + * ``` * * @param attrs Collection of the attributes to apply to this element. */ @@ -506,17 +529,17 @@ open class Node(val nodeName: String) : Element { * Adds a set of attributes to the current element. * @see [attribute] * - * - * "url" { - * attributes( - * "key" to "value", - * "id" to "1" - * ) - * } - * + * ``` + * "url" { + * attributes( + * "key" to "value", + * "id" to "1" + * ) + * } + * ``` * * @param namespace Optional namespace object to use to build the name of the attribute. Note this does NOT declare - * the namespace. It simple uses it to build the attribute name(s). + * the namespace. It simply uses it to build the attribute name(s). * @param attrs Collection of the attributes to apply to this element. */ fun attributes(namespace: Namespace, vararg attrs: Pair) { @@ -536,21 +559,20 @@ open class Node(val nodeName: String) : Element { * Adds the supplied text as a processing instruction element * * @param text The inner text of the processing instruction element. - * @param attribtes Optional set of attributes to apply to this processing instruction. + * @param attributes Optional set of attributes to apply to this processing instruction. */ - fun processingInstruction(text: String, vararg attribtes: Pair) { - _children.add(ProcessingInstructionElement(text, linkedMapOf(*attribtes))) + fun processingInstruction(text: String, vararg attributes: Pair) { + _children.add(ProcessingInstructionElement(text, linkedMapOf(*attributes))) } - /** * Adds the supplied text as a processing instruction element to the root of the document. * * @param text The inner text of the processing instruction element. - * @param attribtes Optional set of attributes to apply to this processing instruction. + * @param attributes Optional set of attributes to apply to this processing instruction. */ - fun globalProcessingInstruction(text: String, vararg attribtes: Pair) { - _globalLevelProcessingInstructions.add(ProcessingInstructionElement(text, linkedMapOf(*attribtes))) + fun globalProcessingInstruction(text: String, vararg attributes: Pair) { + _globalLevelProcessingInstructions.add(ProcessingInstructionElement(text, linkedMapOf(*attributes))) } /** @@ -570,11 +592,11 @@ open class Node(val nodeName: String) : Element { /** * Adds the specified namespace to the element. - * - * "url" { - * namespace("t", "http://someurl.org") - * } - * + * ``` + * "url" { + * namespace("t", "http://someurl.org") + * } + * ``` * * @param name The name of the namespace. * @param value The url or descriptor of the namespace. @@ -587,12 +609,12 @@ open class Node(val nodeName: String) : Element { /** * Adds the specified namespace to the element. - * - * val ns = Namespace("t", "http://someurl.org") - * "url" { - * namespace(ns) - * } - * + * ``` + * val ns = Namespace("t", "http://someurl.org") + * "url" { + * namespace(ns) + * } + * ``` * * @param namespace The namespace object to use for the element's namespace declaration. */ @@ -601,54 +623,199 @@ open class Node(val nodeName: String) : Element { } /** - * Adds a node to the element. + * Adds a node to the node. * @param node The node to append. */ - fun addNode(node: Node) { - node.parent = this - _children.add(node) + @Deprecated( + message = "Use addElement instead", + replaceWith = ReplaceWith("addElement(node)") + ) + fun addNode(node: Node) = addElement(node) + + /** + * Adds a element to the node. + * @param element The element to append. + */ + fun addElement(element: Element) { + setParentIfNode(element, this) + _children.add(element) } /** - * Adds a node to the element after the specific node. + * Adds the provided elements to the node. + * @param elements The elements to append. + */ + fun addElements(vararg elements: Element) = elements.forEach { addElement(it) } + + /** + * Adds the provided elements to the node. + * @param elements The elements to append. + */ + fun addElements(elements: Iterable) = elements.forEach { addElement(it) } + + /** + * Adds a node to the node after the specific node. * @param node The node to add * @param after The node to add [node] after * * @throws IllegalArgumentException If [after] can't be found */ - fun addNodeAfter(node: Node, after: Node) { + @Deprecated( + message = "Use addElementAfter instead", + replaceWith = ReplaceWith("addElementAfter(node, after)") + ) + fun addNodeAfter(node: Node, after: Node) = addElementAfter(node, after) + + /** + * Adds an element to the node after the specific element. + * @param element The element to add + * @param after The element to add [element] after + * + * @throws IllegalArgumentException If [after] can't be found + */ + fun addElementAfter(element: Element, after: Element) { val index = findIndex(after) - node.parent = this + setParentIfNode(element, this) if (index + 1 == _children.size) { - _children.add(node) + _children.add(element) + } else { + _children.add(index + 1, element) + } + } + + /** + * Adds elements to the node after the specific element. + * @param elements The elements to add + * @param after The element to add [elements] after + * + * @throws IllegalArgumentException If [after] can't be found + */ + fun addElementsAfter(elements: Iterable, after: Element) { + val index = findIndex(after) + 1 + + if (index == _children.size) { + addElements(elements) } else { - _children.add(index + 1, node) + val firstPart = _children.take(index) + val lastPart = _children.drop(index) + _children.clear() + _children.addAll(firstPart) + addElements(elements) + _children.addAll(lastPart) } } /** - * Adds a node to the element before the specific node. + * Adds elements to the node after the specific element. + * @param after The element to add [elements] after + * @param elements The elements to add + * + * @throws IllegalArgumentException If [after] can't be found + */ + fun addElementsAfter(after: Element, vararg elements: Element) = + addElementsAfter(listOf(*elements), after) + + /** + * Adds a node to the node before the specific node. * @param node The node to add * @param before The node to add [node] before * * @throws IllegalArgumentException If [before] can't be found */ - fun addNodeBefore(node: Node, before: Node) { - node.parent = this - _children.add(findIndex(before), node) + @Deprecated( + message = "Use addElementBefore instead", + replaceWith = ReplaceWith("addElementBefore(node, before)") + ) + fun addNodeBefore(node: Node, before: Node) = addElementBefore(node, before) + + /** + * Adds an element to the node before the specific element. + * @param element The element to add + * @param before The element to add [element] before + * + * @throws IllegalArgumentException If [before] can't be found + */ + fun addElementBefore(element: Element, before: Element) { + val index = findIndex(before) + setParentIfNode(element, this) + _children.add(index, element) + } + + /** + * Adds elements to the node before the specific element. + * @param elements The elements to add + * @param before The element to add [elements] before + * + * @throws IllegalArgumentException If [before] can't be found + */ + fun addElementsBefore(elements: Iterable, before: Element) { + val index = findIndex(before) + val firstPart = _children.take(index) + val lastPart = _children.drop(index) + _children.clear() + _children.addAll(firstPart) + addElements(elements) + _children.addAll(lastPart) } /** - * Removes a node from the element + * Adds elements to the node before the specific element. + * @param before The element to add [elements] before + * @param elements The elements to add + * + * @throws IllegalArgumentException If [before] can't be found + */ + fun addElementsBefore(before: Element, vararg elements: Element) = + addElementsBefore(listOf(*elements), before) + + /** + * Removes a node from the node * @param node The node to remove * * @throws IllegalArgumentException If [node] can't be found */ - fun removeNode(node: Node) { - val index = findIndex(node) - _children.removeAt(index) + @Deprecated( + message = "Use removeElement instead", + replaceWith = ReplaceWith("removeElement(node)") + ) + fun removeNode(node: Node) = removeElement(node) + + /** + * Removes an element from the node + * @param element The element to remove + * + * @throws IllegalArgumentException If [element] can't be found + */ + fun removeElement(element: Element) { + val index = findIndex(element) + removeChildAt(index) + } + + /** + * Removes the elements from the node + * @param elements The elements to remove + * + * @throws IllegalArgumentException If any [elements] can't be found + */ + fun removeElements(vararg elements: Element) = removeElements(listOf(*elements)) + + /** + * Removes the elements from the node + * @param elements The elements to remove + * + * @throws IllegalArgumentException If any [elements] can't be found + */ + fun removeElements(elements: Iterable) = + elements + .map { findIndex(it) } + .sortedDescending() + .forEach { removeChildAt(it) } + + private fun removeChildAt(index: Int) { + val child = _children.removeAt(index) + setParentIfNode(child, null) } /** @@ -658,12 +825,26 @@ open class Node(val nodeName: String) : Element { * * @throws IllegalArgumentException If [existing] can't be found */ - fun replaceNode(existing: Node, newNode: Node) { + @Deprecated( + message = "Use replaceElement instead", + replaceWith = ReplaceWith("replaceElement(exising, newNode)") + ) + fun replaceNode(existing: Node, newNode: Node) = replaceElement(existing, newNode) + + /** + * Replaces an element with a different element + * @param existing The existing element to replace + * @param newElement The element to replace [existing] with + * + * @throws IllegalArgumentException If [existing] can't be found + */ + fun replaceElement(existing: Element, newElement: Element) { val index = findIndex(existing) - newNode.parent = this - _children.removeAt(index) - _children.add(index, newNode) + setParentIfNode(newElement, this) + setParentIfNode(existing, null) + + _children[index] = newElement } /** @@ -710,13 +891,17 @@ open class Node(val nodeName: String) : Element { private fun filterChildrenToNodes(): List = _children.filterIsInstance(Node::class.java) - private fun findIndex(node: Node): Int { - val index = _children.indexOf(node) - if (index == -1) { - throw IllegalArgumentException("Node with nodeName '${node.nodeName}' is not a child of '$nodeName'") - } + private fun findIndex(element: Element): Int { + return _children + .indexOfFirst { it === element } + .takeUnless { it == -1 } + ?: throw IllegalArgumentException("Element (${element.javaClass} is not a child of '$nodeName'") + } - return index + private fun setParentIfNode(element: Element, newParent: Node?) { + if (element is Node) { + element.parent = newParent + } } override fun equals(other: Any?): Boolean { @@ -725,21 +910,21 @@ open class Node(val nodeName: String) : Element { } return EqualsBuilder() - .append(nodeName, other.nodeName) - .append(encoding, other.encoding) - .append(version, other.version) - .append(_attributes, other._attributes) - .append(_globalLevelProcessingInstructions, other._globalLevelProcessingInstructions) - .append(_children, other._children) - .isEquals + .append(nodeName, other.nodeName) + .append(encoding, other.encoding) + .append(version, other.version) + .append(_attributes, other._attributes) + .append(_globalLevelProcessingInstructions, other._globalLevelProcessingInstructions) + .append(_children, other._children) + .isEquals } override fun hashCode(): Int = HashCodeBuilder() - .append(nodeName) - .append(encoding) - .append(version) - .append(_attributes) - .append(_globalLevelProcessingInstructions) - .append(_children) - .toHashCode() -} \ No newline at end of file + .append(nodeName) + .append(encoding) + .append(version) + .append(_attributes) + .append(_globalLevelProcessingInstructions) + .append(_children) + .toHashCode() +} diff --git a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/PrintOptions.kt b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/PrintOptions.kt index 9a0e902..fb6dc1d 100644 --- a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/PrintOptions.kt +++ b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/PrintOptions.kt @@ -56,4 +56,4 @@ class PrintOptions( val indent: String = "\t" ) { internal var xmlVersion: XmlVersion = XmlVersion.V10 -} \ No newline at end of file +} diff --git a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/ProcessingInstructionElement.kt b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/ProcessingInstructionElement.kt index 9e72732..dbd0509 100644 --- a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/ProcessingInstructionElement.kt +++ b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/ProcessingInstructionElement.kt @@ -5,7 +5,8 @@ import org.apache.commons.lang3.builder.HashCodeBuilder /** * Similar to a [TextElement] except that the inner text is wrapped inside tag. */ -class ProcessingInstructionElement internal constructor(text: String, private val attributes: Map) : TextElement(text) { +class ProcessingInstructionElement internal constructor(text: String, private val attributes: Map) : + TextElement(text) { override fun renderedText(printOptions: PrintOptions): String { return "" } @@ -29,7 +30,7 @@ class ProcessingInstructionElement internal constructor(text: String, private va } override fun hashCode(): Int = HashCodeBuilder() - .appendSuper(super.hashCode()) - .append(attributes) - .toHashCode() -} \ No newline at end of file + .appendSuper(super.hashCode()) + .append(attributes) + .toHashCode() +} diff --git a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/sitemap.kt b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Sitemap.kt similarity index 72% rename from kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/sitemap.kt rename to kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Sitemap.kt index d55da01..65a6c28 100644 --- a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/sitemap.kt +++ b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Sitemap.kt @@ -5,16 +5,17 @@ import java.util.* const val DEFAULT_URLSET_NAMESPACE = "http://www.sitemaps.org/schemas/sitemap/0.9" -class UrlSet internal constructor(): Node("urlset") { +class UrlSet internal constructor() : Node("urlset") { init { xmlns = DEFAULT_URLSET_NAMESPACE } fun url( - loc: String, - lastmod: Date? = null, - changefreq: ChangeFreq? = null, - priority: Double? = null) { + loc: String, + lastmod: Date? = null, + changefreq: ChangeFreq? = null, + priority: Double? = null + ) { "url" { "loc"(loc) @@ -33,14 +34,15 @@ class UrlSet internal constructor(): Node("urlset") { } } -class Sitemapindex internal constructor(): Node("sitemapindex") { +class Sitemapindex internal constructor() : Node("sitemapindex") { init { xmlns = DEFAULT_URLSET_NAMESPACE } fun sitemap( - loc: String, - lastmod: Date? = null) { + loc: String, + lastmod: Date? = null + ) { "sitemap" { "loc"(loc) @@ -51,6 +53,7 @@ class Sitemapindex internal constructor(): Node("sitemapindex") { } } +@Suppress("EnumEntryName", "ktlint:enum-entry-name-case") enum class ChangeFreq { always, hourly, @@ -67,4 +70,4 @@ private fun formatDate(date: Date): String { fun urlset(init: UrlSet.() -> Unit) = UrlSet().apply(init) -fun sitemapindex(init: Sitemapindex.() -> Unit) = Sitemapindex().apply(init) \ No newline at end of file +fun sitemapindex(init: Sitemapindex.() -> Unit) = Sitemapindex().apply(init) diff --git a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Unsafe.kt b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Unsafe.kt index ba730af..23539f5 100644 --- a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Unsafe.kt +++ b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Unsafe.kt @@ -1,3 +1,3 @@ package org.redundent.kotlin.xml -class Unsafe(val value: Any?) \ No newline at end of file +class Unsafe(val value: Any?) diff --git a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/utils.kt b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Utils.kt similarity index 93% rename from kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/utils.kt rename to kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Utils.kt index 2a987d4..54863f2 100644 --- a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/utils.kt +++ b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/Utils.kt @@ -10,7 +10,7 @@ internal fun escapeValue(value: Any?, xmlVersion: XmlVersion, useCharacterRefere return referenceCharacter(asString) } - return when(xmlVersion) { + return when (xmlVersion) { XmlVersion.V10 -> StringEscapeUtils.escapeXml10(asString) XmlVersion.V11 -> StringEscapeUtils.escapeXml11(asString) } @@ -36,4 +36,4 @@ internal fun referenceCharacter(asString: String): String { internal fun buildName(name: String, namespace: Namespace?): String = if (namespace == null || namespace.isDefault) name else "${namespace.name}:$name" -fun unsafe(value: Any?): Unsafe = Unsafe(value) \ No newline at end of file +fun unsafe(value: Any?): Unsafe = Unsafe(value) diff --git a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/XmlBuilder.kt b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/XmlBuilder.kt index d4738da..2a9f294 100644 --- a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/XmlBuilder.kt +++ b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/XmlBuilder.kt @@ -16,11 +16,17 @@ internal fun getLineEnding(printOptions: PrintOptions) = if (printOptions.pretty * @param root The root element name * @param encoding The encoding to use for the xml prolog * @param version The XML specification version to use for the xml prolog and attribute encoding - * @param namespace Optional namespace object to use to build the name of the attribute. This will also an xmlns + * @param namespace Optional namespace object to use to build the name of the attribute. This will also add an xmlns * attribute for this value * @param init The block that defines the content of the xml */ -fun xml(root: String, encoding: String? = null, version: XmlVersion? = null, namespace: Namespace? = null, init: (Node.() -> Unit)? = null): Node { +fun xml( + root: String, + encoding: String? = null, + version: XmlVersion? = null, + namespace: Namespace? = null, + init: (Node.() -> Unit)? = null +): Node { val node = Node(buildName(root, namespace)) if (encoding != null) { node.encoding = encoding @@ -56,9 +62,14 @@ fun node(name: String, namespace: Namespace? = null, init: (Node.() -> Unit)? = fun parse(f: File): Node = parse(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(f)) fun parse(uri: String): Node = parse(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(uri)) -fun parse(inputSource: InputSource): Node = parse(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputSource)) -fun parse(inputStream: InputStream): Node = parse(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream)) -fun parse(inputStream: InputStream, systemId: String): Node = parse(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream, systemId)) +fun parse(inputSource: InputSource): Node = + parse(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputSource)) + +fun parse(inputStream: InputStream): Node = + parse(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream)) + +fun parse(inputStream: InputStream, systemId: String): Node = + parse(DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream, systemId)) fun parse(document: Document): Node { val root = document.documentElement @@ -69,8 +80,8 @@ fun parse(document: Document): Node { val children = root.childNodes (0 until children.length) - .map(children::item) - .forEach { copy(it, result) } + .map(children::item) + .forEach { copy(it, result) } return result } @@ -84,14 +95,16 @@ private fun copy(source: W3CNode, dest: Node) { val children = source.childNodes (0 until children.length) - .map(children::item) - .forEach { copy(it, cur) } + .map(children::item) + .forEach { copy(it, cur) } } + W3CNode.CDATA_SECTION_NODE -> { dest.cdata(source.nodeValue) } + W3CNode.TEXT_NODE -> { - dest.text(source.nodeValue.trim { it.isWhitespace() || it == '\r' || it == '\n' }) + dest.text(source.nodeValue.trim { it.isWhitespace() || it == '\r' || it == '\n' }) } } } @@ -103,12 +116,12 @@ private fun copyAttributes(source: W3CNode, dest: Node) { } (0 until attributes.length) - .map(attributes::item) - .forEach { - if (it.nodeName.startsWith("xmlns")) { - dest.namespace(it.nodeName.substring(min(6, it.nodeName.length)), it.nodeValue) - } else { - dest.attribute(it.nodeName, it.nodeValue) - } + .map(attributes::item) + .forEach { + if (it.nodeName.startsWith("xmlns")) { + dest.namespace(it.nodeName.substring(min(6, it.nodeName.length)), it.nodeValue) + } else { + dest.attribute(it.nodeName, it.nodeValue) } + } } diff --git a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/XmlType.kt b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/XmlType.kt index d9d5a64..85b360d 100644 --- a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/XmlType.kt +++ b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/XmlType.kt @@ -1,3 +1,3 @@ package org.redundent.kotlin.xml -annotation class XmlType(val childOrder: Array) \ No newline at end of file +annotation class XmlType(val childOrder: Array) diff --git a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/XmlVersion.kt b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/XmlVersion.kt index be32ffc..25ee3f8 100644 --- a/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/XmlVersion.kt +++ b/kotlin-xml-builder/src/main/kotlin/org/redundent/kotlin/xml/XmlVersion.kt @@ -3,4 +3,4 @@ package org.redundent.kotlin.xml enum class XmlVersion(val value: String) { V10("1.0"), V11("1.1") -} \ No newline at end of file +} diff --git a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/CDATAElementTest.kt b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/CDATAElementTest.kt index b0b863e..b2cfaa2 100644 --- a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/CDATAElementTest.kt +++ b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/CDATAElementTest.kt @@ -45,4 +45,4 @@ class CDATAElementTest { assertEquals(text1, text2) assertEquals(text2, text1) } -} \ No newline at end of file +} diff --git a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/CommentTest.kt b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/CommentTest.kt index 76691b4..2c98de1 100644 --- a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/CommentTest.kt +++ b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/CommentTest.kt @@ -45,4 +45,4 @@ class CommentTest { assertEquals(comment1, comment2) assertEquals(comment2, comment1) } -} \ No newline at end of file +} diff --git a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/NodeTest.kt b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/NodeTest.kt index 4b3530e..e0a6a2f 100644 --- a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/NodeTest.kt +++ b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/NodeTest.kt @@ -4,8 +4,9 @@ import org.junit.Test import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertNotEquals +import kotlin.test.assertSame -class NodeTest { +class NodeTest : TestBase() { @Test fun `equals null`() { val xml = xml("test") @@ -33,8 +34,8 @@ class NodeTest { @Test fun equals() { val xml1 = xml("complex_node", encoding = "utf-8", version = XmlVersion.V11) { - xmlns = "http://test.com" - namespace("t", "http://t.co") + xmlns = "https://test.com" + namespace("t", "https://t.co") globalProcessingInstruction("global_pi", "global" to "top_level") @@ -51,8 +52,8 @@ class NodeTest { } val xml2 = xml("complex_node", encoding = "utf-8", version = XmlVersion.V11) { - xmlns = "http://test.com" - namespace("t", "http://t.co") + xmlns = "https://test.com" + namespace("t", "https://t.co") globalProcessingInstruction("global_pi", "global" to "top_level") @@ -75,8 +76,8 @@ class NodeTest { @Test fun `equals slight difference`() { val xml1 = xml("complex_node", encoding = "utf-8", version = XmlVersion.V11) { - xmlns = "http://test.com" - namespace("t", "http://t.co") + xmlns = "https://test.com" + namespace("t", "https://t.co") globalProcessingInstruction("global_pi", "global" to "top_level") @@ -93,8 +94,8 @@ class NodeTest { } val xml2 = xml("complex_node", encoding = "utf-8", version = XmlVersion.V11) { - xmlns = "http://test.com" - namespace("t", "http://t.co") + xmlns = "https://test.com" + namespace("t", "https://t.co") globalProcessingInstruction("global_pi", "global" to "top_level") @@ -135,4 +136,106 @@ class NodeTest { xml.set("myAttr", null) assertFalse(xml.hasAttribute("myAttr")) } -} \ No newline at end of file + + @Test + fun `addElements varargs`() { + val xml = xml("root") + + val text = TextElement("test") + val cdata = CDATAElement("cdata") + + xml.addElements(text, cdata) + + assertSame(text, xml.children[0], "first child is text element") + assertSame(cdata, xml.children[1], "second child is cdata element") + } + + @Test + fun `addElements iterable`() { + val xml = xml("root") + + val text = TextElement("test") + val cdata = CDATAElement("cdata") + + xml.addElements(listOf(text, cdata)) + + assertSame(text, xml.children[0], "first child is text element") + assertSame(cdata, xml.children[1], "second child is cdata element") + } + + @Test(expected = IllegalArgumentException::class) + fun `addElementsAfter not found`() { + val xml = xml("root") + val text = TextElement("test") + xml.addElements(text) + + val after = CDATAElement("cdata") + + xml.addElementsAfter(after, TextElement("new")) + } + + @Test + fun addElementsAfter() { + val after = node("third") + + val xml = xml("root") { + "first"("") + "second"("") + addElement(after) + "fourth"("") + "fifth"("") + } + + xml.addElementsAfter( + after, + node("new1"), + node("new2") + ) + + validate( + xml, + PrintOptions( + singleLineTextElements = true, + useSelfClosingTags = true + ) + ) + } + + @Test(expected = IllegalArgumentException::class) + fun `addElementsBefore not found`() { + val xml = xml("root") + val text = TextElement("test") + xml.addElements(text) + + val before = CDATAElement("cdata") + + xml.addElementsBefore(before, TextElement("new")) + } + + @Test + fun addElementsBefore() { + val before = node("third") + + val xml = xml("root") { + "first"("") + "second"("") + addElement(before) + "fourth"("") + "fifth"("") + } + + xml.addElementsBefore( + before, + node("new1"), + node("new2") + ) + + validate( + xml, + PrintOptions( + singleLineTextElements = true, + useSelfClosingTags = true + ) + ) + } +} diff --git a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/OrderedNodesTest.kt b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/OrderedNodesTest.kt index 452e880..a762d94 100644 --- a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/OrderedNodesTest.kt +++ b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/OrderedNodesTest.kt @@ -2,7 +2,7 @@ package org.redundent.kotlin.xml import org.junit.Test -class OrderedNodesTest : XmlBuilderTestBase() { +class OrderedNodesTest : TestBase() { @Test fun correctOrder() { val xml = structured { diff --git a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/ProcessingInstructionElementTest.kt b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/ProcessingInstructionElementTest.kt index c7ffb71..49dbd1d 100644 --- a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/ProcessingInstructionElementTest.kt +++ b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/ProcessingInstructionElementTest.kt @@ -63,4 +63,4 @@ class ProcessingInstructionElementTest { assertEquals(text1, text2) assertEquals(text2, text1) } -} \ No newline at end of file +} diff --git a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/XmlBuilderTestBase.kt b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/TestBase.kt similarity index 96% rename from kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/XmlBuilderTestBase.kt rename to kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/TestBase.kt index 32afd06..c5b4e4d 100644 --- a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/XmlBuilderTestBase.kt +++ b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/TestBase.kt @@ -14,7 +14,7 @@ import javax.xml.transform.dom.DOMSource import javax.xml.transform.stream.StreamResult import kotlin.test.assertEquals -open class XmlBuilderTestBase { +open class TestBase { @get:Rule val testName = TestName() @@ -38,7 +38,7 @@ open class XmlBuilderTestBase { protected fun validate(xml: Node, printOptions: PrintOptions) { val actual = xml.toString(printOptions) - //Doing a replace to cater for different line endings. + // Doing a replace to cater for different line endings. assertEquals(getExpectedXml(), actual.replace(System.lineSeparator(), "\n"), "actual xml matches what is expected") validateXml(actual) @@ -74,4 +74,4 @@ open class XmlBuilderTestBase { transformer.transform(DOMSource(this), StreamResult(sw)) return sw.toString() } -} \ No newline at end of file +} diff --git a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/TextElementTest.kt b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/TextElementTest.kt index af9618d..a41cbc2 100644 --- a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/TextElementTest.kt +++ b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/TextElementTest.kt @@ -4,7 +4,6 @@ import org.junit.Test import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertNotEquals -import kotlin.test.assertTrue class TextElementTest { @Test @@ -46,4 +45,4 @@ class TextElementTest { assertEquals(text1, text2) assertEquals(text2, text1) } -} \ No newline at end of file +} diff --git a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/UtilsKtTest.kt b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/UtilsKtTest.kt index 9fd5a67..4abc2ff 100644 --- a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/UtilsKtTest.kt +++ b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/UtilsKtTest.kt @@ -21,4 +21,4 @@ class UtilsKtTest { assertEquals(" ", escapedValue, "1.1 escapes \\u000b and \\u000c to and ") } -} \ No newline at end of file +} diff --git a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/XmlBuilderTest.kt b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/XmlBuilderTest.kt index f1994e1..f289ee5 100644 --- a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/XmlBuilderTest.kt +++ b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/XmlBuilderTest.kt @@ -10,7 +10,7 @@ import kotlin.test.assertNotNull import kotlin.test.assertNull import kotlin.test.assertTrue -class XmlBuilderTest : XmlBuilderTestBase() { +class XmlBuilderTest : TestBase() { @Test fun basicTest() { val urlset = xml("urlset") { @@ -142,9 +142,11 @@ class XmlBuilderTest : XmlBuilderTestBase() { @Test fun globalProcessingInstructionElement() { val root = xml("root") { - globalProcessingInstruction("xml-stylesheet", - "key" to "value", - "href" to "http://blah") + globalProcessingInstruction( + "xml-stylesheet", + "key" to "value", + "href" to "http://blah" + ) element("element") { globalProcessingInstruction("test") @@ -184,8 +186,8 @@ class XmlBuilderTest : XmlBuilderTestBase() { } element("attributes") { attributes( - "test" to "value", - "key" to "pair" + "test" to "value", + "key" to "pair" ) } } @@ -200,9 +202,11 @@ class XmlBuilderTest : XmlBuilderTestBase() { @Test fun emptyElement() { - validate(xml("root") { - element("test") - }) + validate( + xml("root") { + element("test") + } + ) } @Test @@ -272,18 +276,22 @@ class XmlBuilderTest : XmlBuilderTestBase() { @Test fun elementAsStringWithAttributes() { - validate(xml("root") { - "name"("attr" to "value", "attr2" to "other") - }) + validate( + xml("root") { + "name"("attr" to "value", "attr2" to "other") + } + ) } @Test fun elementAsStringWithAttributesAndContent() { - validate(xml("root") { - "name"("attr" to "value") { - -"Content" + validate( + xml("root") { + "name"("attr" to "value") { + -"Content" + } } - }) + ) } @Test @@ -300,11 +308,11 @@ class XmlBuilderTest : XmlBuilderTestBase() { assertNotNull(xml["attr"], "attr is not null") assertEquals(value, xml["attr"]!!, "attr getting is correct") - //Update the attr value + // Update the attr value xml["attr"] = "something else" assertEquals("something else", xml["attr"]!!, "attr value is updated") - //Remove the + // Remove the xml.xmlns = null assertNull(xml.xmlns, "xmlns is removed") @@ -379,92 +387,92 @@ class XmlBuilderTest : XmlBuilderTestBase() { } @Test - fun addNode() { + fun addElement() { val root = xml("root") { "a"() } - root.addNode(node("b")) + root.addElement(node("b")) validate(root) } @Test - fun removeNode() { + fun removeElement() { val root = xml("root") { "a"() "b"() } - root.removeNode(root.first("b")) + root.removeElement(root.first("b")) validate(root) } @Test - fun addNodeAfter() { + fun addElementAfter() { val root = xml("root") { "a"() "b"() } - root.addNodeAfter(node("c"), root.first("a")) + root.addElementAfter(node("c"), root.first("a")) validate(root) } @Test - fun addNodeAfterLastChild() { + fun addElementAfterLastChild() { val root = xml("root") { "a"() "b"() } - root.addNodeAfter(node("c"), root.first("b")) + root.addElementAfter(node("c"), root.first("b")) validate(root) } @Test(expected = IllegalArgumentException::class) - fun addNodeAfterNonExistent() { + fun addElementAfterNonExistent() { val root = xml("root") { "a"() "b"() } - root.addNodeAfter(node("c"), node("d")) + root.addElementAfter(node("c"), node("d")) } @Test - fun addNodeBefore() { + fun addElementBefore() { val root = xml("root") { "a"() "b"() } - root.addNodeBefore(node("c"), root.first("b")) + root.addElementBefore(node("c"), root.first("b")) validate(root) } @Test(expected = IllegalArgumentException::class) - fun addNodeBeforeNonExistent() { + fun addElementBeforeNonExistent() { val root = xml("root") { "a"() "b"() } - root.addNodeBefore(node("c"), node("d")) + root.addElementBefore(node("c"), node("d")) } @Test - fun replaceNode() { + fun replaceElement() { val root = xml("root") { "a"() "b"() } - root.replaceNode(root.first("b"), node("c")) + root.replaceElement(root.first("b"), node("c")) validate(root) } @@ -584,6 +592,7 @@ class XmlBuilderTest : XmlBuilderTestBase() { validate(root) } + @Test fun doctypePublic() { val root = xml("root") { @@ -610,9 +619,11 @@ class XmlBuilderTest : XmlBuilderTestBase() { } "child" { - attributes(ns5, + attributes( + ns5, "key1" to "value1", - "key2" to "value2") + "key2" to "value2" + ) attributes( Attribute("key3", "value3", ns6), Attribute("key4", "value4", ns1) diff --git a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/sitemapTest.kt b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/sitemapTest.kt index 4a8cd29..73ea085 100644 --- a/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/sitemapTest.kt +++ b/kotlin-xml-builder/src/test/kotlin/org/redundent/kotlin/xml/sitemapTest.kt @@ -3,7 +3,7 @@ package org.redundent.kotlin.xml import org.junit.Test import java.text.SimpleDateFormat -class sitemapTest : XmlBuilderTestBase() { +class sitemapTest : TestBase() { @Test fun basicTest() { val urlset = urlset { @@ -18,10 +18,12 @@ class sitemapTest : XmlBuilderTestBase() { @Test fun allElements() { val urlset = urlset { - url("http://blog.redundent.org", - SimpleDateFormat("yyyy-MM-dd").parse("2017-10-24"), - ChangeFreq.hourly, - 14.0) + url( + "http://blog.redundent.org", + SimpleDateFormat("yyyy-MM-dd").parse("2017-10-24"), + ChangeFreq.hourly, + 14.0 + ) } validate(urlset) } @@ -37,4 +39,4 @@ class sitemapTest : XmlBuilderTestBase() { validate(sitemapIndex) } -} \ No newline at end of file +} diff --git a/kotlin-xml-builder/src/test/resources/test-results/NodeTest/addElementsAfter.xml b/kotlin-xml-builder/src/test/resources/test-results/NodeTest/addElementsAfter.xml new file mode 100644 index 0000000..a5cfbec --- /dev/null +++ b/kotlin-xml-builder/src/test/resources/test-results/NodeTest/addElementsAfter.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/kotlin-xml-builder/src/test/resources/test-results/NodeTest/addElementsBefore.xml b/kotlin-xml-builder/src/test/resources/test-results/NodeTest/addElementsBefore.xml new file mode 100644 index 0000000..a84b094 --- /dev/null +++ b/kotlin-xml-builder/src/test/resources/test-results/NodeTest/addElementsBefore.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/addNode.xml b/kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/addElement.xml similarity index 100% rename from kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/addNode.xml rename to kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/addElement.xml diff --git a/kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/addNodeAfter.xml b/kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/addElementAfter.xml similarity index 100% rename from kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/addNodeAfter.xml rename to kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/addElementAfter.xml diff --git a/kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/addNodeAfterLastChild.xml b/kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/addElementAfterLastChild.xml similarity index 100% rename from kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/addNodeAfterLastChild.xml rename to kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/addElementAfterLastChild.xml diff --git a/kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/addNodeBefore.xml b/kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/addElementBefore.xml similarity index 100% rename from kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/addNodeBefore.xml rename to kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/addElementBefore.xml diff --git a/kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/removeNode.xml b/kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/removeElement.xml similarity index 100% rename from kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/removeNode.xml rename to kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/removeElement.xml diff --git a/kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/replaceNode.xml b/kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/replaceElement.xml similarity index 100% rename from kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/replaceNode.xml rename to kotlin-xml-builder/src/test/resources/test-results/XmlBuilderTest/replaceElement.xml diff --git a/kotlin-xml-dsl-generator/build.gradle.kts b/kotlin-xml-dsl-generator/build.gradle.kts index 92e946b..2a53f1d 100644 --- a/kotlin-xml-dsl-generator/build.gradle.kts +++ b/kotlin-xml-dsl-generator/build.gradle.kts @@ -5,6 +5,7 @@ plugins { id("com.github.johnrengelman.shadow") version "5.2.0" `maven-publish` signing + id("org.jlleitschuh.gradle.ktlint") } val kotlinVersion: String by rootProject.extra diff --git a/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/DslGenerator.kt b/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/DslGenerator.kt index a4fdca7..c7dd3a2 100644 --- a/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/DslGenerator.kt +++ b/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/DslGenerator.kt @@ -14,7 +14,8 @@ import kotlin.system.exitProcess fun main(args: Array) { try { val opts = ExOptions().apply { parseArguments(args) } - val output = File(opts.targetDir, "${opts.defaultPackage.replace(".", File.separator)}${File.separator}schema.kt") + val output = + File(opts.targetDir, "${opts.defaultPackage.replace(".", File.separator)}${File.separator}schema.kt") println("\nGenerating schema to ${output.absolutePath}") @@ -39,7 +40,8 @@ fun main(args: Array) { } fun usage() { - println("""Usage: java -jar kotlin-xml-dsl-generator.jar [-options ...] ... [-b ] ... + println( + """Usage: java -jar kotlin-xml-dsl-generator.jar [-options ...] ... [-b ] ... Options: -b : specify external JAXB bindings files @@ -52,7 +54,7 @@ Options: class DslGenerator(private val opts: ExOptions) { fun generate(): String { val model = ModelLoader.load(opts, JCodeModel(), ErrReceiver()) - ?: throw BadCommandLineException("Something failed generating the code model") + ?: throw BadCommandLineException("Something failed generating the code model") val outline = BeanGenerator.generate(model, ErrReceiver()) @@ -60,7 +62,15 @@ class DslGenerator(private val opts: ExOptions) { val schemaOutline = SchemaOutline(outline, opts) codeWriter.writeSuppress { - addAll(listOf("PropertyName", "ReplaceArrayOfWithLiteral", "LocalVariableName", "FunctionName", "RemoveRedundantBackticks")) + addAll( + listOf( + "PropertyName", + "ReplaceArrayOfWithLiteral", + "LocalVariableName", + "FunctionName", + "RemoveRedundantBackticks" + ) + ) if (schemaOutline.enums.isNotEmpty()) { add("EnumEntryName") @@ -102,4 +112,4 @@ class ExOptions : Options() { return super.parseArgument(args, i) } -} \ No newline at end of file +} diff --git a/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/SchemaOutline.kt b/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/SchemaOutline.kt index 46996c8..2a79e50 100644 --- a/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/SchemaOutline.kt +++ b/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/SchemaOutline.kt @@ -26,4 +26,4 @@ class SchemaOutline(outline: Outline, private val opts: ExOptions) { recurseInnerClasses(innerClass) } } -} \ No newline at end of file +} diff --git a/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/Code.kt b/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/Code.kt index a71bbcb..f9bb673 100644 --- a/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/Code.kt +++ b/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/Code.kt @@ -2,4 +2,4 @@ package org.redundent.kotlin.xml.gen.writer interface Code { fun write(codeWriter: CodeWriter) -} \ No newline at end of file +} diff --git a/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/XmlAttribute.kt b/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/XmlAttribute.kt index ec3677d..3a6dbd4 100644 --- a/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/XmlAttribute.kt +++ b/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/XmlAttribute.kt @@ -1,9 +1,9 @@ package org.redundent.kotlin.xml.gen.writer class XmlAttribute( - val name: String, - val type: String, - private val isRequired: Boolean + val name: String, + val type: String, + private val isRequired: Boolean ) : Code { override fun write(codeWriter: CodeWriter) { codeWriter.writeln("var `$name`: $type") @@ -12,4 +12,4 @@ class XmlAttribute( codeWriter.writeln("set(value) { set(\"$name\", value) }") codeWriter.dedent() } -} \ No newline at end of file +} diff --git a/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/XmlClass.kt b/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/XmlClass.kt index fc95950..6d1d6ba 100644 --- a/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/XmlClass.kt +++ b/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/XmlClass.kt @@ -4,13 +4,16 @@ import com.sun.tools.xjc.outline.ClassOutline import org.redundent.kotlin.xml.gen.ExOptions class XmlClass( - val clazz: ClassOutline, - private val opts: ExOptions, - innerClass: Boolean = false) : Code { + val clazz: ClassOutline, + private val opts: ExOptions, + innerClass: Boolean = false +) : Code { val name: String = clazz.target.shortName - val xmlns: String? = if (clazz.target.isElement && clazz.target.elementName.namespaceURI.isNotBlank()) clazz.target.elementName.namespaceURI else null + val xmlns: String? = + if (clazz.target.isElement && clazz.target.elementName.namespaceURI.isNotBlank()) clazz.target.elementName.namespaceURI else null - private val superClassName: String = clazz.superClass?.target?.let { "${it.ownerPackage.name()}.`${it.shortName}`" } ?: "Node" + private val superClassName: String = + clazz.superClass?.target?.let { "${it.ownerPackage.name()}.`${it.shortName}`" } ?: "Node" private val abstract: Boolean = clazz.target.isAbstract private val attributes: MutableList = ArrayList() private val memberElements: MutableList = ArrayList() @@ -27,7 +30,7 @@ class XmlClass( private val superClassConstructorArg = if (innerClass) "\"$name\"" else "nodeName" private val hasBody: Boolean - get() = attributes.isNotEmpty() || xmlns != null || innerClasses.isNotEmpty() || (opts.useMemberFunctions && memberElements.isNotEmpty()) + get() = attributes.isNotEmpty() || xmlns != null || innerClasses.isNotEmpty() || (opts.useMemberFunctions && memberElements.isNotEmpty()) init { clazz.target.attributes.map { @@ -40,7 +43,15 @@ class XmlClass( clazz.target.elements.forEach { element -> element.types.forEach { type -> - memberElements.add(XmlElement(type.tagName.localPart, type.target, type.tagName.localPart, element.documentation, if (opts.useMemberFunctions) null else clazz.target)) + memberElements.add( + XmlElement( + type.tagName.localPart, + type.target, + type.tagName.localPart, + element.documentation, + if (opts.useMemberFunctions) null else clazz.target + ) + ) } } @@ -51,7 +62,7 @@ class XmlClass( } override fun write(codeWriter: CodeWriter) { - with (codeWriter) { + with(codeWriter) { writeKotlinDoc(clazz.target.documentation) if (clazz.target.isOrdered && clazz.target.elements.size > 1) { @@ -106,4 +117,4 @@ init { fun addInnerClass(xmlClass: XmlClass) { innerClasses.add(xmlClass) } -} \ No newline at end of file +} diff --git a/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/XmlElement.kt b/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/XmlElement.kt index 54cb6d7..e06dfb5 100644 --- a/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/XmlElement.kt +++ b/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/XmlElement.kt @@ -4,15 +4,16 @@ import com.sun.tools.xjc.model.CClassInfo import com.sun.tools.xjc.model.CNonElement class XmlElement( - val name: String, - val type: CNonElement, - private val tagName: String, - private val documentation: String?, - private val parent: CClassInfo? = null) : Code { + val name: String, + val type: CNonElement, + private val tagName: String, + private val documentation: String?, + private val parent: CClassInfo? = null +) : Code { override fun write(codeWriter: CodeWriter) { val rootElement = parent == null - with (codeWriter) { + with(codeWriter) { writeKotlinDoc(documentation) val funLine = "fun ${if (!rootElement) "`${parent!!.shortName}`." else ""}`$name`" @@ -24,9 +25,13 @@ class XmlElement( write(funLine) if (type is CClassInfo) { - val blockParamType = "${((type.parent() as? CClassInfo)?.let { "`${it.shortName}`." } ?: "")}`${type.shortName}`" + val blockParamType = + "${((type.parent() as? CClassInfo)?.let { "`${it.shortName}`." } ?: "")}`${type.shortName}`" - writeln("(${type.attributesAsParameters(funLine.length + (currentIndex * 4) + 1)}__block__: $blockParamType.() -> Unit)${if (rootElement) ": `${type.shortName}`" else ""} {", false) + writeln( + "(${type.attributesAsParameters(funLine.length + (currentIndex * 4) + 1)}__block__: $blockParamType.() -> Unit)${if (rootElement) ": `${type.shortName}`" else ""} {", + false + ) indent() writeln("val `$tagName` = `${type.shortName}`(${if (type.parent() is CClassInfo) "" else "\"$tagName\""})") if (type.allAttributes.isNotEmpty()) { @@ -50,7 +55,7 @@ class XmlElement( if (rootElement) { writeln("return `$tagName`") } else { - writeln("this.addNode(`$tagName`)") + writeln("this.addElement(`$tagName`)") } dedent() @@ -65,4 +70,4 @@ class XmlElement( } } } -} \ No newline at end of file +} diff --git a/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/XmlEnum.kt b/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/XmlEnum.kt index 85ce8de..29076b2 100644 --- a/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/XmlEnum.kt +++ b/kotlin-xml-dsl-generator/src/main/kotlin/org/redundent/kotlin/xml/gen/writer/XmlEnum.kt @@ -4,7 +4,7 @@ import com.sun.tools.xjc.outline.EnumOutline class XmlEnum(private val enum: EnumOutline) : Code { override fun write(codeWriter: CodeWriter) { - with (codeWriter) { + with(codeWriter) { writeKotlinDoc(enum.target.documentation) writeln("enum class `${enum.target.shortName}` {") indent() @@ -14,4 +14,4 @@ class XmlEnum(private val enum: EnumOutline) : Code { writeln("}\n") } } -} \ No newline at end of file +} diff --git a/kotlin-xml-dsl-generator/src/test/kotlin/org/redundent/kotlin/xml/gen/AbstractGenTest.kt b/kotlin-xml-dsl-generator/src/test/kotlin/org/redundent/kotlin/xml/gen/AbstractGenTest.kt index 9879c2f..d7287b9 100644 --- a/kotlin-xml-dsl-generator/src/test/kotlin/org/redundent/kotlin/xml/gen/AbstractGenTest.kt +++ b/kotlin-xml-dsl-generator/src/test/kotlin/org/redundent/kotlin/xml/gen/AbstractGenTest.kt @@ -3,6 +3,7 @@ package org.redundent.kotlin.xml.gen import org.junit.Rule import org.junit.rules.TestName import java.io.File +import java.io.FileNotFoundException import java.io.InputStream import java.io.InputStreamReader import kotlin.test.assertEquals @@ -14,6 +15,7 @@ abstract class AbstractGenTest { protected fun run(withBindingFile: Boolean = false, vararg additionalArgs: String) { val schema = javaClass.getResourceAsStream("/schema/${testName.methodName}.xsd") + ?: throw FileNotFoundException("/schema/${testName.methodName}.xsd as not found") val code = getExpectedClassText() val file = File.createTempFile("schema", ".xsd").apply { @@ -26,6 +28,7 @@ abstract class AbstractGenTest { if (withBindingFile) { val binding = javaClass.getResourceAsStream("/schema/${testName.methodName}.jxb") + ?: throw FileNotFoundException("/schema/${testName.methodName}.jxb as not found") val bindingFile = File.createTempFile("binding", ".jxb").apply { writer().use { writer -> binding.reader().forEachLine { line -> @@ -52,9 +55,10 @@ abstract class AbstractGenTest { private fun getInputStream(): InputStream { val resName = "/code/${testName.methodName}.kt" return javaClass.getResourceAsStream(resName) + ?: throw FileNotFoundException("$resName as not found") } private fun cleanText(text: String): String { return text.split("\n").joinToString("\n", transform = String::trimEnd) } -} \ No newline at end of file +} diff --git a/kotlin-xml-dsl-generator/src/test/kotlin/org/redundent/kotlin/xml/gen/SimpleSchemGen.kt b/kotlin-xml-dsl-generator/src/test/kotlin/org/redundent/kotlin/xml/gen/SimpleSchemaGen.kt similarity index 93% rename from kotlin-xml-dsl-generator/src/test/kotlin/org/redundent/kotlin/xml/gen/SimpleSchemGen.kt rename to kotlin-xml-dsl-generator/src/test/kotlin/org/redundent/kotlin/xml/gen/SimpleSchemaGen.kt index 1028266..d0732da 100644 --- a/kotlin-xml-dsl-generator/src/test/kotlin/org/redundent/kotlin/xml/gen/SimpleSchemGen.kt +++ b/kotlin-xml-dsl-generator/src/test/kotlin/org/redundent/kotlin/xml/gen/SimpleSchemaGen.kt @@ -2,7 +2,7 @@ package org.redundent.kotlin.xml.gen import org.junit.Test -class SimpleSchemGen : AbstractGenTest() { +class SimpleSchemaGen : AbstractGenTest() { @Test fun sitemap() = run() @@ -41,4 +41,4 @@ class SimpleSchemGen : AbstractGenTest() { @Test fun `member-functions`() = run(additionalArgs = arrayOf("--use-member-functions")) -} \ No newline at end of file +} diff --git a/kotlin-xml-dsl-generator/src/test/resources/code/choice.kt b/kotlin-xml-dsl-generator/src/test/resources/code/choice.kt index e01b397..e12932f 100644 --- a/kotlin-xml-dsl-generator/src/test/resources/code/choice.kt +++ b/kotlin-xml-dsl-generator/src/test/resources/code/choice.kt @@ -9,19 +9,19 @@ open class `MethodName`(nodeName: String) : Node(nodeName) fun `MethodName`.`type1`(__block__: `Type1`.() -> Unit) { val `type1` = `Type1`("type1") `type1`.apply(__block__) - this.addNode(`type1`) + this.addElement(`type1`) } fun `MethodName`.`type2`(__block__: `Type2`.() -> Unit) { val `type2` = `Type2`("type2") `type2`.apply(__block__) - this.addNode(`type2`) + this.addElement(`type2`) } fun `MethodName`.`type3`(__block__: `Type3`.() -> Unit) { val `type3` = `Type3`("type3") `type3`.apply(__block__) - this.addNode(`type3`) + this.addElement(`type3`) } fun `Method-Name`(__block__: `MethodName`.() -> Unit): `MethodName` { diff --git a/kotlin-xml-dsl-generator/src/test/resources/code/duplicate-names.kt b/kotlin-xml-dsl-generator/src/test/resources/code/duplicate-names.kt index 3e8efa1..67bf965 100644 --- a/kotlin-xml-dsl-generator/src/test/resources/code/duplicate-names.kt +++ b/kotlin-xml-dsl-generator/src/test/resources/code/duplicate-names.kt @@ -11,7 +11,7 @@ open class `DuplicateNameContainer`(nodeName: String) : Node(nodeName) { fun `DuplicateNameContainer`.`DuplicateName`(__block__: `DuplicateNameContainer`.`DuplicateName`.() -> Unit) { val `DuplicateName` = `DuplicateName`() `DuplicateName`.apply(__block__) - this.addNode(`DuplicateName`) + this.addElement(`DuplicateName`) } open class `DuplicateNames`(nodeName: String) : org.redundent.generated.`DuplicateNameContainer`(nodeName) diff --git a/kotlin-xml-dsl-generator/src/test/resources/code/nested.kt b/kotlin-xml-dsl-generator/src/test/resources/code/nested.kt index e069289..fa046e1 100644 --- a/kotlin-xml-dsl-generator/src/test/resources/code/nested.kt +++ b/kotlin-xml-dsl-generator/src/test/resources/code/nested.kt @@ -27,7 +27,7 @@ open class `Top`(nodeName: String) : Node(nodeName) { } } `second`.apply(__block__) - this.addNode(`second`) + this.addElement(`second`) } } @@ -38,7 +38,7 @@ fun `Top`.`first`(`Id`: kotlin.Long, this.`Id` = `Id` } `first`.apply(__block__) - this.addNode(`first`) + this.addElement(`first`) } fun `top`(__block__: `Top`.() -> Unit): `Top` { diff --git a/kotlin-xml-dsl-generator/src/test/resources/code/sitemap.kt b/kotlin-xml-dsl-generator/src/test/resources/code/sitemap.kt index c59ae3e..8c09489 100644 --- a/kotlin-xml-dsl-generator/src/test/resources/code/sitemap.kt +++ b/kotlin-xml-dsl-generator/src/test/resources/code/sitemap.kt @@ -35,7 +35,7 @@ open class `Urlset`(nodeName: String) : Node(nodeName) { fun `Urlset`.`url`(__block__: `TUrl`.() -> Unit) { val `url` = `TUrl`("url") `url`.apply(__block__) - this.addNode(`url`) + this.addElement(`url`) } /** diff --git a/settings.gradle.kts b/settings.gradle.kts index 3827ef6..52833eb 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,4 +2,3 @@ rootProject.name = "kotlin-xml-builder" include(":kotlin-xml-dsl-generator") include(":kotlin-xml-builder") -