mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 16:53:04 +08:00
refactor(common): extract shared XML Block base and reuse it in BlockContent and TaskBlock
This commit is contained in:
@@ -0,0 +1,123 @@
|
|||||||
|
package work.slhaf.partner.common.base
|
||||||
|
|
||||||
|
import org.w3c.dom.Document
|
||||||
|
import org.w3c.dom.Element
|
||||||
|
import java.io.StringWriter
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory
|
||||||
|
import javax.xml.transform.OutputKeys
|
||||||
|
import javax.xml.transform.TransformerFactory
|
||||||
|
import javax.xml.transform.dom.DOMSource
|
||||||
|
import javax.xml.transform.stream.StreamResult
|
||||||
|
|
||||||
|
abstract class Block(
|
||||||
|
val blockName: String
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun encodeToXml(): Element {
|
||||||
|
val document = DocumentBuilderFactory.newInstance()
|
||||||
|
.newDocumentBuilder()
|
||||||
|
.newDocument()
|
||||||
|
|
||||||
|
val root = document.createElement(blockName)
|
||||||
|
document.appendChild(root)
|
||||||
|
appendRootAttributes().forEach { attribute, value -> root.setAttribute(attribute, value) }
|
||||||
|
fillXml(document, root)
|
||||||
|
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun appendRootAttributes(): Map<String, String> {
|
||||||
|
return emptyMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun encodeToXmlString(): String {
|
||||||
|
val transformer = TransformerFactory.newInstance().newTransformer().apply {
|
||||||
|
setOutputProperty(OutputKeys.INDENT, "yes")
|
||||||
|
setOutputProperty(OutputKeys.ENCODING, "UTF-8")
|
||||||
|
setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2")
|
||||||
|
}
|
||||||
|
|
||||||
|
return StringWriter().use { writer ->
|
||||||
|
transformer.transform(DOMSource(encodeToXml()), StreamResult(writer))
|
||||||
|
writer.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun fillXml(document: Document, root: Element)
|
||||||
|
|
||||||
|
protected fun appendTextElement(
|
||||||
|
document: Document,
|
||||||
|
parent: Element,
|
||||||
|
tagName: String,
|
||||||
|
value: Any?
|
||||||
|
): Element {
|
||||||
|
val element = document.createElement(tagName)
|
||||||
|
element.textContent = value?.toString() ?: ""
|
||||||
|
parent.appendChild(element)
|
||||||
|
return element
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun appendChildElement(
|
||||||
|
document: Document,
|
||||||
|
parent: Element,
|
||||||
|
tagName: String,
|
||||||
|
block: Element.() -> Unit = {}
|
||||||
|
): Element {
|
||||||
|
val element = document.createElement(tagName)
|
||||||
|
parent.appendChild(element)
|
||||||
|
element.block()
|
||||||
|
return element
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun appendCDataElement(
|
||||||
|
document: Document,
|
||||||
|
parent: Element,
|
||||||
|
tagName: String,
|
||||||
|
value: String?
|
||||||
|
): Element {
|
||||||
|
val element = document.createElement(tagName)
|
||||||
|
element.appendChild(document.createCDATASection(value ?: ""))
|
||||||
|
parent.appendChild(element)
|
||||||
|
return element
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
|
protected fun <T> appendListElement(
|
||||||
|
document: Document,
|
||||||
|
parent: Element,
|
||||||
|
wrapperTagName: String,
|
||||||
|
itemTagName: String,
|
||||||
|
values: Iterable<T>,
|
||||||
|
block: Element.(T) -> Unit = { value ->
|
||||||
|
textContent = value?.toString() ?: ""
|
||||||
|
}
|
||||||
|
): Element {
|
||||||
|
val wrapper = document.createElement(wrapperTagName)
|
||||||
|
parent.appendChild(wrapper)
|
||||||
|
|
||||||
|
for (value in values) {
|
||||||
|
val item = document.createElement(itemTagName)
|
||||||
|
wrapper.appendChild(item)
|
||||||
|
item.block(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
|
protected fun <T> appendRepeatedElements(
|
||||||
|
document: Document,
|
||||||
|
parent: Element,
|
||||||
|
itemTagName: String,
|
||||||
|
values: Iterable<T>,
|
||||||
|
block: Element.(T) -> Unit = { value ->
|
||||||
|
textContent = value?.toString() ?: ""
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
for (value in values) {
|
||||||
|
val item = document.createElement(itemTagName)
|
||||||
|
parent.appendChild(item)
|
||||||
|
item.block(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,16 +2,11 @@ package work.slhaf.partner.core.cognition
|
|||||||
|
|
||||||
import org.w3c.dom.Document
|
import org.w3c.dom.Document
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import java.io.StringWriter
|
import work.slhaf.partner.common.base.Block
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
import javax.xml.parsers.DocumentBuilderFactory
|
|
||||||
import javax.xml.transform.OutputKeys
|
|
||||||
import javax.xml.transform.TransformerFactory
|
|
||||||
import javax.xml.transform.dom.DOMSource
|
|
||||||
import javax.xml.transform.stream.StreamResult
|
|
||||||
import kotlin.concurrent.write
|
import kotlin.concurrent.write
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
@@ -318,10 +313,10 @@ private class AggregatedBlockContent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class BlockContent @JvmOverloads protected constructor(
|
abstract class BlockContent @JvmOverloads protected constructor(
|
||||||
val blockName: String,
|
blockName: String,
|
||||||
val source: String,
|
val source: String,
|
||||||
val urgency: Urgency = Urgency.NORMAL
|
val urgency: Urgency = Urgency.NORMAL
|
||||||
) {
|
) : Block(blockName) {
|
||||||
|
|
||||||
enum class Urgency {
|
enum class Urgency {
|
||||||
LOW,
|
LOW,
|
||||||
@@ -330,111 +325,13 @@ abstract class BlockContent @JvmOverloads protected constructor(
|
|||||||
CRITICAL
|
CRITICAL
|
||||||
}
|
}
|
||||||
|
|
||||||
fun encodeToXml(): Element {
|
override fun appendRootAttributes(): Map<String, String> {
|
||||||
val document = DocumentBuilderFactory.newInstance()
|
return mapOf(
|
||||||
.newDocumentBuilder()
|
"source" to source,
|
||||||
.newDocument()
|
"urgency" to urgency.name.lowercase(Locale.ROOT)
|
||||||
|
)
|
||||||
val root = document.createElement(blockName)
|
|
||||||
root.setAttribute("source", source)
|
|
||||||
root.setAttribute("urgency", urgency.name.lowercase(Locale.ROOT))
|
|
||||||
document.appendChild(root)
|
|
||||||
|
|
||||||
fillXml(document, root)
|
|
||||||
|
|
||||||
return root
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun encodeToXmlString(): String {
|
|
||||||
val transformer = TransformerFactory.newInstance().newTransformer().apply {
|
|
||||||
setOutputProperty(OutputKeys.INDENT, "yes")
|
|
||||||
setOutputProperty(OutputKeys.ENCODING, "UTF-8")
|
|
||||||
setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2")
|
|
||||||
}
|
|
||||||
|
|
||||||
return StringWriter().use { writer ->
|
|
||||||
transformer.transform(DOMSource(encodeToXml()), StreamResult(writer))
|
|
||||||
writer.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract fun fillXml(document: Document, root: Element)
|
|
||||||
|
|
||||||
protected fun appendTextElement(
|
|
||||||
document: Document,
|
|
||||||
parent: Element,
|
|
||||||
tagName: String,
|
|
||||||
value: Any?
|
|
||||||
): Element {
|
|
||||||
val element = document.createElement(tagName)
|
|
||||||
element.textContent = value?.toString() ?: ""
|
|
||||||
parent.appendChild(element)
|
|
||||||
return element
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun appendChildElement(
|
|
||||||
document: Document,
|
|
||||||
parent: Element,
|
|
||||||
tagName: String,
|
|
||||||
block: Element.() -> Unit = {}
|
|
||||||
): Element {
|
|
||||||
val element = document.createElement(tagName)
|
|
||||||
parent.appendChild(element)
|
|
||||||
element.block()
|
|
||||||
return element
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun appendCDataElement(
|
|
||||||
document: Document,
|
|
||||||
parent: Element,
|
|
||||||
tagName: String,
|
|
||||||
value: String?
|
|
||||||
): Element {
|
|
||||||
val element = document.createElement(tagName)
|
|
||||||
element.appendChild(document.createCDATASection(value ?: ""))
|
|
||||||
parent.appendChild(element)
|
|
||||||
return element
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmOverloads
|
|
||||||
protected fun <T> appendListElement(
|
|
||||||
document: Document,
|
|
||||||
parent: Element,
|
|
||||||
wrapperTagName: String,
|
|
||||||
itemTagName: String,
|
|
||||||
values: Iterable<T>,
|
|
||||||
block: Element.(T) -> Unit = { value ->
|
|
||||||
textContent = value?.toString() ?: ""
|
|
||||||
}
|
|
||||||
): Element {
|
|
||||||
val wrapper = document.createElement(wrapperTagName)
|
|
||||||
parent.appendChild(wrapper)
|
|
||||||
|
|
||||||
for (value in values) {
|
|
||||||
val item = document.createElement(itemTagName)
|
|
||||||
wrapper.appendChild(item)
|
|
||||||
item.block(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
return wrapper
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmOverloads
|
|
||||||
protected fun <T> appendRepeatedElements(
|
|
||||||
document: Document,
|
|
||||||
parent: Element,
|
|
||||||
itemTagName: String,
|
|
||||||
values: Iterable<T>,
|
|
||||||
block: Element.(T) -> Unit = { value ->
|
|
||||||
textContent = value?.toString() ?: ""
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
for (value in values) {
|
|
||||||
val item = document.createElement(itemTagName)
|
|
||||||
parent.appendChild(item)
|
|
||||||
item.block(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class CommunicationBlockContent(
|
abstract class CommunicationBlockContent(
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package work.slhaf.partner.module
|
||||||
|
|
||||||
|
import work.slhaf.partner.api.chat.pojo.Message
|
||||||
|
import work.slhaf.partner.common.base.Block
|
||||||
|
|
||||||
|
abstract class TaskBlock @JvmOverloads constructor(
|
||||||
|
blockName: String = "task_input"
|
||||||
|
) : Block(blockName) {
|
||||||
|
|
||||||
|
fun encodeToMessage(): Message {
|
||||||
|
return Message(Message.Character.USER, encodeToXmlString())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user