将NodeBuilder结果转换为对象层次结构

时间:2013-05-28 00:13:51

标签: groovy

想象一下nodeBuilder用于表示对象层次结构:

class TestBuilder {

static main(args) {

        def builder = new NodeBuilder()
    def ulcDate = new Date(107,0,1)
    def invoices = builder.invoices{
        invoice(date: ulcDate){

            item(count:5){
                product(name:'ULC', dollar:1499)
            }
            item(count:1){
                product(name:'Visual Editor', dollar:499)
            }
        }
        invoice(date: new Date(106,1,2)){
            item(count:4) {
                product(name:'Visual Editor', dollar:499)
            }
        }
    }

}




   class Invoice {
        List items
        Date date
     }

   class LineItem {
        Product product
        int count
        int total() 
        {
            return product.dollar * count
        }
    }

   class Product {
        String name
        def dollar
    }

如何将由NodeBuilder生成的发票对象实际转换为Invoice类的实例,其中包含从发票对象配置的所有内容?我可能必须使用GPath来执行此操作(?)但该代码将如何显示?

我需要这样做的原因是其他类的其他方法需要Invoice类的实例进一步操作,我猜不会接受NodeBuilder输出。

2 个答案:

答案 0 :(得分:2)

我认为最简单的方法就是为您的特定对象集进行节点遍历。

示例:

import groovy.util.*

////////////
// build Node tree as asked in original post

def builder = new NodeBuilder()
def ulcDate = new Date(107,0,1)

def invoices = builder.invoices {
    invoice(date: ulcDate) {
        item(count:5) {
            product(name:'ULC', dollar:1499)
        }
        item(count:1) {
            product(name:'Visual Editor', dollar:499)
        }
    }
    invoice(date: new Date(106,1,2)){
        item(count:4) {
            product(name:'Visual Editor', dollar:499)
        }
    }
}

////////////
// define objects. It is easy to have these in Java

class Invoice {
    def date
    def items = []
}

class Item {
    def count
    def product
}

class Product {
    def name
    def dollar
}

////////////
// convert from nodes to objects

def invoiceNodeList = invoices.get("invoice")
def invoiceList = []

invoiceNodeList.each { def invoiceNode ->
    def date = invoiceNode.attribute("date")
    Invoice invoice = new Invoice(date: date)

    invoiceNode.children().each { def itemNode ->
        def count = itemNode.attribute("count")
        Product product = null
        // assume only one Product per Item, but we'll
        // use children() for simplicity
        itemNode.children().each { def productNode ->
            def name = productNode.attribute("name")
            def dollar = productNode.attribute("dollar")
            product = new Product(name: name, dollar: dollar)
        }
        Item item = new Item(count: count, product: product)
        invoice.items << item
    } 
    invoiceList << invoice
}

////////////
// print out objects 

invoiceList.each { Invoice invoice ->
    println "--------"
    println invoice.date
    invoice.items.each { Item item ->
        println item.count
        println item.product.name
        println item.product.dollar
    }
}

答案 1 :(得分:1)

对您的基类进行轻微调整:

class Invoice {
  List lineItems = []
  Date date

  String toString() {
    String ret = "Invoice $date $lineItems"
  }
}

class LineItem {
  Product product
  int count

  int total() {
    product.dollar * count
  }

  String toString() {
    "$product * $count"
  }
}

class Product {
  String name
  int dollar

  String toString() {
    "$name ($dollar)"
  }
}

表示您可以轻松使用ObjectGraphBuilder来构建列表:

List invoices = new ObjectGraphBuilder(classLoader: getClass().classLoader).with { 
  [
    invoice( date: new Date( 107, 0, 1 ) ) {
      lineItem( count: 5 ) {
        product( name: 'ULC', dollar: 1499 )
      }
      lineItem(count:1){
        product(name:'Visual Editor', dollar:499)
      }
    },
    invoice(date: new Date(106,1,2)){
      lineItem(count:4) {
        product(name:'Visual Editor', dollar:499)
      }
    }
  ]
}

如果无法调整基类,则在构建图表之前can customise how properties are looked up by setting the resolvers