2012-12-19 57 views
4

我想具有在斯波克數據驅動規格的格式的數據集描述:如何爲數據集描述創建spock式的DSL?

'Key' | 'Value' | 'Comments' 
1  | 'foo'  | 'something' 
2  | 'bar'  | 'something else' 

這已被轉化成類似2D陣列(或任何能夠實現)。

任何想法如何實現這個數據描述?

p.s.最大的問題是linebreak檢測,其餘的可以通過在Object的metaClass上重載or來實現。

回答

5

|運算符左結合的,所以在這個表中的一行將被解析,如:

('Key' | 'Value') | 'Comments' 

什麼你就可以做檢測,每一行的開始和結束是讓| opeator返回列表及其操作數,然後每個|詢問左側操作數(即this)是否爲列表。如果是,那麼這意味着它是連續的;如果它不是一個列表,這意味着它是一個新的行。

這裏有一個DSL的一個完整的例子來分析使用Category以避免對對象的元類壓倒一切的事情這些數據集:

@Category(Object) 
class DatasetCategory { 
    // A static property for holding the results of the DSL. 
    static results 

    def or(other) { 
     if (this instanceof List) { 
      // Already in a row. Add the value to the row. 
      return this << other 
     } else { 
      // A new row. 
      def row = [this, other] 
      results << row 
      return row 
     } 
    } 
} 

// This is the method that receives a closure with the DSL and returns the 
// parsed result. 
def dataset(Closure cl) { 
    // Initialize results and execute closure using the DatasetCategory. 
    DatasetCategory.results = [] 
    use (DatasetCategory) { cl() } 

    // Convert the 2D results array into a list of objects: 
    def table = DatasetCategory.results 
    def header = table.head() 
    def rows = table.tail() 
    rows.collect { row -> 
     [header, row].transpose().collectEntries { it } 
    } 
} 

// Example usage. 
def data = dataset { 
    'Key' | 'Value' | 'Comments' 
    1  | 'foo'  | 'something' 
    2  | 'bar'  | 'something else' 
} 

// Correcness test :) 
assert data == [ 
    [Key: 1, Value: 'foo', Comments: 'something'], 
    [Key: 2, Value: 'bar', Comments: 'something else'] 
] 

在這個例子中,我分析的表作爲地圖的列表,但你在DSL關閉運行後,應該能夠對DatasetCategory的結果做任何你想做的事情。

+0

您對Category的解決方案非常棒,謝謝! – Roman