update the DOM API so that we implement using the property style access of properties which work natively in JS and avoid using getter/setter methods in the DOM library so that they can easily compile to JS too from the same org.w3c.dom API on the JVM
This commit is contained in:
@@ -11,23 +11,20 @@ import java.lang.IndexOutOfBoundsException
|
||||
|
||||
// Properties
|
||||
|
||||
val Document?.rootElement : Element?
|
||||
get() = if (this != null) this.getDocumentElement() else null
|
||||
|
||||
|
||||
var Node.text : String
|
||||
get() {
|
||||
if (this.getNodeType() == Node.ELEMENT_NODE) {
|
||||
if (this.nodeType == Node.ELEMENT_NODE) {
|
||||
val buffer = StringBuilder()
|
||||
val nodeList = this.getChildNodes()
|
||||
val nodeList = this.childNodes
|
||||
if (nodeList != null) {
|
||||
var i = 0
|
||||
val size = nodeList.getLength()
|
||||
val size = nodeList.length
|
||||
while (i < size) {
|
||||
val node = nodeList.item(i)
|
||||
if (node != null) {
|
||||
if (node.isText()) {
|
||||
buffer.append(node.getNodeValue())
|
||||
buffer.append(node.nodeValue)
|
||||
}
|
||||
}
|
||||
i++
|
||||
@@ -35,11 +32,11 @@ get() {
|
||||
}
|
||||
return buffer.toString().sure()
|
||||
} else {
|
||||
return this.getNodeValue() ?: ""
|
||||
return this.nodeValue
|
||||
}
|
||||
}
|
||||
set(value) {
|
||||
if (this.getNodeType() == Node.ELEMENT_NODE) {
|
||||
if (this.nodeType == Node.ELEMENT_NODE) {
|
||||
val element = this as Element
|
||||
// lets remove all the previous text nodes first
|
||||
for (node in element.children()) {
|
||||
@@ -74,7 +71,7 @@ set(value) {
|
||||
|
||||
/** Returns the children of the element as a list */
|
||||
inline fun Element?.children(): List<Node> {
|
||||
return this?.getChildNodes().toList()
|
||||
return this?.childNodes.toList()
|
||||
}
|
||||
|
||||
/** The child elements of this document */
|
||||
@@ -175,7 +172,7 @@ class NodeListAsList(val nodeList: NodeList): AbstractList<Node>() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun size(): Int = nodeList.getLength()
|
||||
override fun size(): Int = nodeList.length
|
||||
}
|
||||
|
||||
class ElementListAsList(val nodeList: NodeList): AbstractList<Element>() {
|
||||
@@ -183,14 +180,14 @@ class ElementListAsList(val nodeList: NodeList): AbstractList<Element>() {
|
||||
val node = nodeList.item(index)
|
||||
if (node == null) {
|
||||
throw IndexOutOfBoundsException("NodeList does not contain a node at index: " + index)
|
||||
} else if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||
} else if (node.nodeType == Node.ELEMENT_NODE) {
|
||||
return node as Element
|
||||
} else {
|
||||
throw IllegalArgumentException("Node is not an Element as expected but is $node")
|
||||
}
|
||||
}
|
||||
|
||||
override fun size(): Int = nodeList.getLength()
|
||||
override fun size(): Int = nodeList.length
|
||||
|
||||
}
|
||||
|
||||
@@ -202,7 +199,7 @@ fun Node.nextSiblings() : Iterator<Node> = NextSiblingIterator(this)
|
||||
class NextSiblingIterator(var node: Node) : AbstractIterator<Node>() {
|
||||
|
||||
override fun computeNext(): Unit {
|
||||
val nextValue = node.getNextSibling()
|
||||
val nextValue = node.nextSibling
|
||||
if (nextValue != null) {
|
||||
setNext(nextValue)
|
||||
node = nextValue
|
||||
@@ -218,7 +215,7 @@ fun Node.previousSiblings() : Iterator<Node> = PreviousSiblingIterator(this)
|
||||
class PreviousSiblingIterator(var node: Node) : AbstractIterator<Node>() {
|
||||
|
||||
override fun computeNext(): Unit {
|
||||
val nextValue = node.getPreviousSibling()
|
||||
val nextValue = node.previousSibling
|
||||
if (nextValue != null) {
|
||||
setNext(nextValue)
|
||||
node = nextValue
|
||||
@@ -230,8 +227,8 @@ class PreviousSiblingIterator(var node: Node) : AbstractIterator<Node>() {
|
||||
|
||||
/** Returns true if this node is a Text node or a CDATA node */
|
||||
fun Node.isText(): Boolean {
|
||||
val nodeType = getNodeType()
|
||||
return nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE
|
||||
val nt = nodeType
|
||||
return nt == Node.TEXT_NODE || nt == Node.CDATA_SECTION_NODE
|
||||
}
|
||||
|
||||
/** Returns the attribute value or empty string if its not present */
|
||||
@@ -240,7 +237,7 @@ inline fun Element.attribute(name: String): String {
|
||||
}
|
||||
|
||||
val NodeList?.head : Node?
|
||||
get() = if (this != null && this.getLength() > 0) this.item(0) else null
|
||||
get() = if (this != null && this.length > 0) this.item(0) else null
|
||||
|
||||
val NodeList?.first : Node?
|
||||
get() = this.head
|
||||
@@ -250,7 +247,7 @@ get() {
|
||||
if (this == null) {
|
||||
return null
|
||||
} else {
|
||||
val s = this.getLength()
|
||||
val s = this.length
|
||||
return if (s > 0) this.item(s - 1) else null
|
||||
}
|
||||
}
|
||||
@@ -295,8 +292,8 @@ fun Element.createElement(name: String, doc: Document? = null, init: Element.()-
|
||||
|
||||
/** Returns the owner document of the element or uses the provided document */
|
||||
fun Node.ownerDocument(doc: Document? = null): Document {
|
||||
val answer = if (this != null && this.getNodeType() == Node.DOCUMENT_NODE) this as Document
|
||||
else if (doc == null) this.getOwnerDocument()
|
||||
val answer = if (this != null && this.nodeType == Node.DOCUMENT_NODE) this as Document
|
||||
else if (doc == null) this.ownerDocument
|
||||
else doc
|
||||
|
||||
if (answer == null) {
|
||||
|
||||
@@ -19,6 +19,79 @@ import javax.xml.transform.stream.StreamResult
|
||||
import org.w3c.dom.*
|
||||
import org.xml.sax.InputSource
|
||||
|
||||
val Node.nodeName: String
|
||||
get() = getNodeName() ?: ""
|
||||
|
||||
val Node.nodeValue: String
|
||||
get() = getNodeValue() ?: ""
|
||||
|
||||
val Node.nodeType: Short
|
||||
get() = getNodeType()
|
||||
|
||||
val Node.parentNode: Node?
|
||||
get() = getParentNode()
|
||||
|
||||
val Node.childNodes: NodeList
|
||||
get() = getChildNodes()!!
|
||||
|
||||
val Node.firstChild: Node?
|
||||
get() = getFirstChild()
|
||||
|
||||
val Node.lastChild: Node?
|
||||
get() = getLastChild()
|
||||
|
||||
val Node.nextSibling: Node?
|
||||
get() = getNextSibling()
|
||||
|
||||
val Node.previousSibling: Node?
|
||||
get() = getPreviousSibling()
|
||||
|
||||
val Node.attributes: NamedNodeMap?
|
||||
get() = getAttributes()
|
||||
|
||||
val Node.ownerDocument: Document?
|
||||
get() = getOwnerDocument()
|
||||
|
||||
val Document.documentElement: Element?
|
||||
get() = if (this != null) this.getDocumentElement() else null
|
||||
|
||||
val Node.namespaceURI: String
|
||||
get() = getNamespaceURI() ?: ""
|
||||
|
||||
val Node.prefix: String
|
||||
get() = getPrefix() ?: ""
|
||||
|
||||
val Node.localName: String
|
||||
get() = getLocalName() ?: ""
|
||||
|
||||
val Node.baseURI: String
|
||||
get() = getBaseURI() ?: ""
|
||||
|
||||
var Node.textContent: String
|
||||
get() = getTextContent() ?: ""
|
||||
set(value) {
|
||||
setTextContent(value)
|
||||
}
|
||||
|
||||
val DOMStringList.length: Int
|
||||
get() = this.getLength()
|
||||
|
||||
val NameList.length: Int
|
||||
get() = this.getLength()
|
||||
|
||||
val DOMImplementationList.length: Int
|
||||
get() = this.getLength()
|
||||
|
||||
val NodeList.length: Int
|
||||
get() = this.getLength()
|
||||
|
||||
val CharacterData.length: Int
|
||||
get() = this.getLength()
|
||||
|
||||
val NamedNodeMap.length: Int
|
||||
get() = this.getLength()
|
||||
|
||||
|
||||
/** Returns an [[Iterator]] of all the next [[Element]] siblings */
|
||||
fun Node.nextElements(): Iterator<Element> = nextSiblings().filterIsInstance<Node, Element>(javaClass<Element>())
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ class DomBuilderTest() : TestCase() {
|
||||
assertEquals(1, doc["#id2"].size())
|
||||
assertEquals(1, doc["#id3"].size())
|
||||
|
||||
val root = doc.rootElement
|
||||
val root = doc.documentElement
|
||||
if (root == null) {
|
||||
fail("No root!")
|
||||
} else {
|
||||
@@ -120,7 +120,7 @@ class DomBuilderTest() : TestCase() {
|
||||
} else {
|
||||
fail("Not an Element $grandChild")
|
||||
}
|
||||
val children = doc.rootElement.children()
|
||||
val children = doc.documentElement.children()
|
||||
val xml = nodesToXmlString(children)
|
||||
println("root element has children: ${xml}")
|
||||
assertEquals(1, children.size())
|
||||
|
||||
@@ -3,8 +3,11 @@ package org.jetbrains.kotlin.tools
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
import java.io.PrintWriter
|
||||
import org.w3c.dom.*
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Modifier
|
||||
import java.util.ArrayList
|
||||
import java.util.TreeMap
|
||||
import org.w3c.dom.*
|
||||
|
||||
/**
|
||||
* This tool generates JavaScript stubs for classes available in the JDK which are already available in the browser environment
|
||||
@@ -29,10 +32,10 @@ import js.noImpl
|
||||
|
||||
val classes = arrayList(javaClass<Attr>(), javaClass<CDATASection>(),
|
||||
javaClass<CharacterData>(), javaClass<Comment>(),
|
||||
javaClass<Document>(),javaClass<DocumentFragment>(),javaClass<DocumentType>(),
|
||||
javaClass<Document>(), javaClass<DocumentFragment>(), javaClass<DocumentType>(),
|
||||
javaClass<DOMConfiguration>(),
|
||||
javaClass<DOMError>(), javaClass<DOMErrorHandler>(),
|
||||
javaClass<DOMImplementation>(),
|
||||
javaClass<DOMImplementation>(), javaClass<DOMImplementationList>(),
|
||||
javaClass<DOMLocator>(),
|
||||
javaClass<DOMStringList>(),
|
||||
javaClass<Element>(),
|
||||
@@ -53,31 +56,78 @@ import js.noImpl
|
||||
|
||||
println("native public trait ${klass.getSimpleName()}$extends {")
|
||||
|
||||
// lets iterate through each method
|
||||
val methods = klass.getDeclaredMethods()
|
||||
if (methods != null) {
|
||||
// lets figure out the properties versus methods
|
||||
val validMethods = ArrayList<Method>()
|
||||
val properties = TreeMap<String, String>()
|
||||
for (method in methods) {
|
||||
if (method != null) {
|
||||
val parameterTypes = method.getParameterTypes()!!
|
||||
val name = method.getName() ?: ""
|
||||
fun propertyName(): String {
|
||||
val answer = name.substring(3).decapitalize()
|
||||
return if (answer == "type") {
|
||||
"`type`"
|
||||
} else answer
|
||||
}
|
||||
fun propertyType() = simpleTypeName(method.getReturnType())
|
||||
|
||||
// TODO in java 7 its not easy with reflection to get the parameter argument name...
|
||||
var counter = 0
|
||||
val parameters = parameterTypes.map<Class<out Any?>?, String>{ "arg${++counter}: ${simpleTypeName(it)}" }.makeString(", ")
|
||||
val returnType = simpleTypeName(method.getReturnType())
|
||||
println(" fun ${method.getName()}($parameters): $returnType = js.noImpl")
|
||||
val params = method.getParameterTypes()
|
||||
val paramSize = params?.size ?: 0
|
||||
if (name.size > 3) {
|
||||
if (name.startsWith("get") && paramSize == 0) {
|
||||
val propName = propertyName()
|
||||
if (!properties.containsKey(propName)) {
|
||||
properties.put(propName, "public val $propName: ${propertyType()}")
|
||||
}
|
||||
} else if (name.startsWith("set") && paramSize == 0) {
|
||||
val propName = propertyName()
|
||||
properties.put(propName, "public var $propName: ${propertyType()}")
|
||||
} else {
|
||||
validMethods.add(method)
|
||||
}
|
||||
} else {
|
||||
validMethods.add(method)
|
||||
}
|
||||
}
|
||||
}
|
||||
for (statement in properties.values()) {
|
||||
println(" $statement")
|
||||
}
|
||||
for (method in validMethods) {
|
||||
val parameterTypes = method.getParameterTypes()!!
|
||||
|
||||
// TODO in java 7 its not easy with reflection to get the parameter argument name...
|
||||
var counter = 0
|
||||
val parameters = parameterTypes.map<Class<out Any?>?, String>{ "arg${++counter}: ${simpleTypeName(it)}" }.makeString(", ")
|
||||
val returnType = simpleTypeName(method.getReturnType())
|
||||
println(" public fun ${method.getName()}($parameters): $returnType = js.noImpl")
|
||||
}
|
||||
}
|
||||
val fields = klass.getDeclaredFields()
|
||||
if (fields != null) {
|
||||
for (field in fields) {
|
||||
if (field != null) {
|
||||
val modifiers = field.getModifiers()
|
||||
if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers)) {
|
||||
val fieldType = simpleTypeName(field.getType())
|
||||
println(" public val ${field.getName()}: $fieldType")
|
||||
if (fields.notEmpty()) {
|
||||
println("")
|
||||
println(" class object {")
|
||||
for (field in fields) {
|
||||
if (field != null) {
|
||||
val modifiers = field.getModifiers()
|
||||
if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers)) {
|
||||
val fieldType = simpleTypeName(field.getType())
|
||||
try {
|
||||
val value = field.get(null)
|
||||
if (value != null) {
|
||||
val fieldType = simpleTypeName(field.getType())
|
||||
println(" public val ${field.getName()}: $fieldType = $value")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println("Caught: $e")
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
println(" }")
|
||||
}
|
||||
}
|
||||
println("}")
|
||||
|
||||
Reference in New Issue
Block a user