Groovy12_Json、xml、swing与生成器

1. Json 生成器 : JsonBuilder

import groovy.json.JsonBuilder
import groovy.json.JsonOutput
import groovy.json.JsonSlurper

""""""
// json 生成器
def builder = new JsonBuilder()
builder.json{
    first 'zeking'
    last 'haha'
}

println builder  // {"json":{"first":"zeking","last":"haha"}}

builder{
    first 'zeking'
    last 'haha'
}

println builder  // {"first":"zeking","last":"haha"}

class Person{
    def first
    def last
}

def p = new Person(first: 'zekign',last:'haha')
// 转换对象为json数据
def b = new JsonBuilder(p)
println b.toString()      // {"first":"zekign","last":"haha"}

println JsonOutput.toJson(p) // {"first":"zekign","last":"haha"}
// 格式化json数据
println JsonOutput.prettyPrint(JsonOutput.toJson(p))
//{
//    "first": "zekign",
//    "last": "haha"
//}

// 反序列化
def slurper = new JsonSlurper()
Person person = slurper.parseText(JsonOutput.toJson(p))
println person.first  // zekign
println person.last   // haha

2.xml 生成器 : MarkupBuilder

2.1 创建xml

xml_create.groovy

import groovy.xml.MarkupBuilder
import groovy.xml.StreamingMarkupBuilder

// xml 生成

"""<html><head m="a">hello</head></html>"""

//new File("baidu.html").write("https://www.baidu.com/".toURL().text)
def sw = new FileWriter(new File("normal.xml"))
def builder = new MarkupBuilder(sw)
builder.html{
    mkp.comment("测试")  // 注释
    head("hello",m:"a"){
        title("ZekingLee")
    }
    body{

    }
}

//<html><!-- 测试 -->
//  <head m='a'>hello
//    <title>ZekingLee</title>
//  </head>
//  <body />
//</html>

def sb = new StreamingMarkupBuilder()
sb.encoding = 'UTF-8'
def closure = {
    // 生成xml文件的版本和标识的方法
    mkp.xmlDeclaration()
    html{
        head(id:1){

        }
    }
}
def sw2 = sb.bind(closure)

println sw2.toString()
// <?xml version='1.0' encoding='UTF-8'?>
// <html><head id='1'></head></html>
2.2 解析xml

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.administrator.androidprotobuf">

    <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">

        <meta-data android:name="hello" android:value="1"/>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

xml_parse.groovy

import groovy.xml.Namespace

// parser 是个Node  就是 manifest节点
def parser = new XmlParser().parse(new File("AndroidManifest.xml"))

// 1.需求:拿到activity节点的name属性
// name属性有一个 android: 的命名空间

//命名空间
def ns = new Namespace('http://schemas.android.com/apk/res/android','android')

Node node = parser.application[0].activity[0]
println node.attributes()[ns.name]    // .MainActivity


// 2.移除meta-data节点,添加节点
// 获得application节点
Node node2 = parser.application[0]
//NodeList
Node meta = node2.'meta-data'[0]
node2.remove(meta)
node2.appendNode('meta-data',[(ns.name):'a',(ns.value):'b',(ns.hh):'hh'])
new XmlNodePrinter(new PrintWriter(new File("replace.xml"))).print(parser)

//<manifest package="com.example.administrator.androidprotobuf">
//  <application android:allowBackup="true" xmlns:android="http://schemas.android.com/apk/res/android" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">
//    <activity android:name=".MainActivity">
//      <intent-filter>
//        <action android:name="android.intent.action.MAIN"/>
//        <category android:name="android.intent.category.LAUNCHER"/>
//      </intent-filter>
//    </activity>
//    <meta-data android:name="a" android:value="b" android:hh="hh"/>
//  </application>
//</manifest>
//</manifest>

3. swing生成器 :SwingBuilder

import groovy.swing.SwingBuilder

import javax.swing.JButton
import javax.swing.JFrame
import javax.swing.JLabel
import javax.swing.WindowConstants
import java.awt.FlowLayout

// 使用groovy 写
def builder  = new SwingBuilder()
def swing = builder.frame(title: '测试',size: [100,100],
        layout: new FlowLayout(),defaultCloseOperation: WindowConstants.EXIT_ON_CLOSE){
    label(text:'文本')
    button(text:'按钮',actionPerformed:{

    })
}
swing.setVisible(true)

// 使用java代码写 ,对比一下,groovy简单很多
//def frame = new JFrame()
//frame.setTitle('测试')
//frame.setSize(100,100)
//frame.setLayout(new FlowLayout())
//frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
//new JLabel()
//new JButton().addActionListener {
//
//}

4. 模仿xm生成器 的 BuilderSupport自定义html生成器

MyBuildSupport.groovy

package builder
// 模仿xm生成器 的 MarkupBuilder 自定义生成器
class MyBuildSupport extends BuilderSupport{


    class Node{
        String name
        String value
        Map attr
        def children // 将Node这个节点的所有子节点都保存到这个集合里面

        Node(String name, String value, Map attr) {
            this.name = name
            this.value = value
            this.attr = attr
            children = []
        }

        //<xml key='value'/>
        //<xml>xxx</xml>
        def build(Writer writer){
            // 生成xml
            writer.write("<$name")
            if (attr){
                attr.each {
                    key,value->
                        writer.write(" $key='$value")
                }
            }
            if (value || children){
                writer.write(">")
                if (value){
                    writer.write(value)
                }
                children.each{
                    it.build(writer)
                }
                writer.write("</$name>")
            }else {
                writer.write("/>")
            }
        }
    }

    def nodes
    Writer writer
    MyBuildSupport(Writer writer){
        nodes = [:]
        this.writer = writer
    }

    /**
     * 节点与节点的关系
     * @param parent    父节点
     * @param child     子节点
     */
    @Override
    protected void setParent(Object parent, Object child) {
        println "seParent $parent $child" // 这样是没有任何回调的
        // 如何有回调,createNode 的 返回值会作为seParent的 参数 传递过来
    }

    /**
     * 完成节点调用
     * 通过这个方法可以知道
     * 节点之间的关系 也可以知道 节点的完成情况
     * @param parent
     * @param node
     */
    @Override
    protected void nodeCompleted(Object parent, Object node) {
        super.nodeCompleted(parent, node)
        println "nodeCompleted $parent $node"
        def currentNode = nodes[node]
        if (parent){
            nodes[parent].children << currentNode
        }else{
            // 构建需要的格式
            currentNode.build(writer)
        }
    }

    @Override
    protected Object createNode(Object name) {
        return createNode(name,null,null)
    }

    @Override
    protected Object createNode(Object name, Object value) {
        return createNode(name,null,value)
    }

    @Override
    protected Object createNode(Object name, Map attributes) {
        return createNode(name,attributes,null)
    }

    @Override
    protected Object createNode(Object name, Map attributes, Object value) {
        println("create Node:$name $value $attributes")
        nodes.put(name,new Node(name,value,attributes))
        return name
    }
}

MyBuilderTest.groovy

package builder

StringWriter sw = new StringWriter()
def builder = new MyBuildSupport(sw)
builder.html{
    head("zeking",key:'value'){
        title("Test")
    }

    body{

    }
    x{
        y{
            z{

            }
        }
    }
}

println(sw)
//create Node:html null null
//create Node:head zeking [key:value]
//seParent html head
//create Node:title Test null
//seParent head title
//nodeCompleted head title
//nodeCompleted html head
//create Node:body null null
//seParent html body
//nodeCompleted html body
//create Node:x null null
//seParent html x
//create Node:y null null
//seParent x y
//create Node:z null null
//seParent y z
//nodeCompleted y z
//nodeCompleted x y
//nodeCompleted html x
//nodeCompleted null html
//<html><head key='value>zeking<title>Test</title></head><body/><x><y><z/></y></x></html>

5. 模仿swing生成器 的 FactoryBuilderSupport自定义html生成器

MyFactoryBuilderSupport.groovy

package builder

// 模仿swing生成器
// 工厂 buildsupport工厂

class Node{
    String name
    String value
    Map attr
    def children // 将Node这个节点的所有子节点都保存到这个集合里面

    Node(String name, String value, Map attr) {
        this.name = name
        this.value = value
        this.attr = attr
        children = []
    }

    //<xml key='value'/>
    //<xml>xxx</xml>
    def build(Writer writer){
        // 生成xml
        writer.write("<$name")
        if (attr){
            attr.each {
                key,value->
                    writer.write(" $key='$value")
            }
        }
        if (value || children){
            writer.write(">")
            if (value){
                writer.write(value)
            }
            children.each{
                it.build(writer)
            }
            writer.write("</$name>")
        }else {
            writer.write("/>")
        }
    }
}

class MyFactoryBuilderSupport extends FactoryBuilderSupport{

    {
        def nodeFactory = new NodeFactory()
        // 注册html的工厂
        registerFactory('html',new NodeFactory())
        registerFactory('head',new NodeFactory())
    }
}


class NodeFactory extends AbstractFactory{

    def name

    /**
     * 返回的参数就是我们调用html方法的结果
     * @param builder
     * @param name
     * @param value
     * @param attributes
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    @Override
    Object newInstance(FactoryBuilderSupport builder, Object name, Object value, Map attributes) throws InstantiationException, IllegalAccessException {
        println "newInstance $name $value $attributes"
        this.name = name
        return new Node(name,value,attributes)
    }

    // 在newInstance 之后调用
    // 处理属性的方法
    @Override
    boolean onHandleNodeAttributes(FactoryBuilderSupport builder, Object node, Map attributes) {
        //如果返回true会从newInstance返回中寻找attributes对应key的属性
        return false
    }

    // false 表示可以接收闭包
    // true  表示不能接收
    @Override
    boolean isLeaf() {
        return super.isLeaf()
    }

    // 设置当前节点的父节点
    @Override
    void setParent(FactoryBuilderSupport builder, Object parent, Object child) {
        super.setParent(builder, parent, child)
        println "$name setParent ${parent.name} ${child.name}"
    }

    // 设置当前节点的子节点
    @Override
    void setChild(FactoryBuilderSupport builder, Object parent, Object child) {
        super.setChild(builder, parent, child)
        println "$name setChild ${parent.name} ${child.name}"
        parent.children << child
    }
}



MyFactoryBuilderSupportTest.groovy

package builder



//new MyFactoryBuilderSupport().xml{
//
//}
// 会报错,因为我没有注册xml工厂
//五月 16, 2018 10:11:22 下午 groovy.util.FactoryBuilderSupport createNode
//警告: Could not find match for name 'xml'
//Caught: groovy.lang.MissingMethodException: No signature of method: java.lang.Object.xml() is applicable for argument types: (java.util.Collections$EmptyMap, null) values: [[:], null]
//Possible solutions: dump(), any(), wait(), find(), grep(), is(java.lang.Object)
//groovy.lang.MissingMethodException: No signature of method: java.lang.Object.xml() is applicable for argument types: (java.util.Collections$EmptyMap, null) values: [[:], null]
//Possible solutions: dump(), any(), wait(), find(), grep(), is(java.lang.Object)
//  at builder.MyFactoryBuilderSupportTest.run(MyFactoryBuilderSupportTest.groovy:5)

//new MyFactoryBuilderSupport().html{
//
//}
// 不会报错,只是警告 这就是registerFactory 的作用
//五月 16, 2018 10:11:01 下午 groovy.util.FactoryBuilderSupport createNode
//警告: Factory for name 'html' returned null

StringWriter sw = new StringWriter()
new MyFactoryBuilderSupport().html{
    head('Zeking',key:'value'){

    }
}.build(sw)
println sw

//newInstance html null [:]
//newInstance head Zeking [key:value]
//head setParent html head
//html setChild html head
//<html><head key='value>Zeking</head></html>

6. FactoryBuilderSupport 和 BuilderSupport 的区别

FactoryBuilderSupport 适用于 固定的方法,必须注册工厂
而BuilderSupport 可以用户高度自定义
FactoryBuilderSupport不适合创建html 但是会非常适合创建swing

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值