1

想象一下 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 生成的 invoices 对象实际转换为 Invoice 类的实例,其中所有内容都从 invoices 对象配置?我可能必须使用 GPath 才能这样做(?)但是该代码会是什么样子?

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

4

2 回答 2

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
    }
}
于 2013-05-28T04:17:03.527 回答
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)
      }
    }
  ]
}

如果无法调整基类,您可以通过在构建图表之前设置解析器来自定义属性的查找方式

于 2013-05-28T08:26:56.797 回答