From fb9b3860af35f219eb23c61a167c9d3522dfb2e5 Mon Sep 17 00:00:00 2001 From: slhafzjw Date: Thu, 26 Mar 2026 20:43:26 +0800 Subject: [PATCH] refactor(common): extract shared XML `Block` base and reuse it in `BlockContent` and `TaskBlock` --- .../work/slhaf/partner/common/base/Block.kt | 123 ++++++++++++++++++ .../core/cognition/ContextWorkspace.kt | 119 ++--------------- .../work/slhaf/partner/module/TaskBlock.kt | 14 ++ 3 files changed, 145 insertions(+), 111 deletions(-) create mode 100644 Partner-Core/src/main/java/work/slhaf/partner/common/base/Block.kt create mode 100644 Partner-Core/src/main/java/work/slhaf/partner/module/TaskBlock.kt diff --git a/Partner-Core/src/main/java/work/slhaf/partner/common/base/Block.kt b/Partner-Core/src/main/java/work/slhaf/partner/common/base/Block.kt new file mode 100644 index 00000000..f4d5a4b4 --- /dev/null +++ b/Partner-Core/src/main/java/work/slhaf/partner/common/base/Block.kt @@ -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 { + 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 appendListElement( + document: Document, + parent: Element, + wrapperTagName: String, + itemTagName: String, + values: Iterable, + 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 appendRepeatedElements( + document: Document, + parent: Element, + itemTagName: String, + values: Iterable, + block: Element.(T) -> Unit = { value -> + textContent = value?.toString() ?: "" + } + ) { + for (value in values) { + val item = document.createElement(itemTagName) + parent.appendChild(item) + item.block(value) + } + } +} \ No newline at end of file diff --git a/Partner-Core/src/main/java/work/slhaf/partner/core/cognition/ContextWorkspace.kt b/Partner-Core/src/main/java/work/slhaf/partner/core/cognition/ContextWorkspace.kt index c4ffec5d..fe7aa393 100644 --- a/Partner-Core/src/main/java/work/slhaf/partner/core/cognition/ContextWorkspace.kt +++ b/Partner-Core/src/main/java/work/slhaf/partner/core/cognition/ContextWorkspace.kt @@ -2,16 +2,11 @@ package work.slhaf.partner.core.cognition import org.w3c.dom.Document import org.w3c.dom.Element -import java.io.StringWriter +import work.slhaf.partner.common.base.Block import java.time.Duration import java.time.Instant import java.util.* 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.math.max import kotlin.math.min @@ -318,10 +313,10 @@ private class AggregatedBlockContent( } abstract class BlockContent @JvmOverloads protected constructor( - val blockName: String, + blockName: String, val source: String, val urgency: Urgency = Urgency.NORMAL -) { +) : Block(blockName) { enum class Urgency { LOW, @@ -330,111 +325,13 @@ abstract class BlockContent @JvmOverloads protected constructor( CRITICAL } - fun encodeToXml(): Element { - val document = DocumentBuilderFactory.newInstance() - .newDocumentBuilder() - .newDocument() - - 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 + override fun appendRootAttributes(): Map { + return mapOf( + "source" to source, + "urgency" to urgency.name.lowercase(Locale.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 appendListElement( - document: Document, - parent: Element, - wrapperTagName: String, - itemTagName: String, - values: Iterable, - 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 appendRepeatedElements( - document: Document, - parent: Element, - itemTagName: String, - values: Iterable, - 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( diff --git a/Partner-Core/src/main/java/work/slhaf/partner/module/TaskBlock.kt b/Partner-Core/src/main/java/work/slhaf/partner/module/TaskBlock.kt new file mode 100644 index 00000000..e4f53e14 --- /dev/null +++ b/Partner-Core/src/main/java/work/slhaf/partner/module/TaskBlock.kt @@ -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()) + } + +} \ No newline at end of file