2016-08-04 6 views
2

私は現在、小さなDSLを構築していますが、キー=値のペアでプロパティのセットを指定する必要がありますが、キーにダッシュやピリオドを入れることがあります。私はそれを動作させるように見えることはできません。無効なキーでDSL用groovyマップを使用する

私は基本的にクロージャへのデリゲートとしてマップを渡してみますが、構文は引き続き魅力的です。

例として、このことを考慮してください。

def map = [:] 

map.with { 
    example1 = 123 
    //exam-ple2 = 123 
    //'exam-ple3' = 123 
    //(exam-ple4) = 123 
    exam.ple5 = 123 
    //'exam.ple6' = 123 
} 

例1は結構です、キーは値と簡単に読めると等しいです。例2と4は、コンパイラによるバイナリ表現であり、コンパイルされません。例3と6は定数式であり、コンパイルされません。例5はコンパイルされますが、実行時にはNPEが生成されます。

私は例3と6を与えている閉包の引数としてマップを渡すような回避策を使用できますが、その冗長性は私を煩わします。

プロパティマップをきれいにDSLする方法はありますか?ところで

:解析側のトリックは、Javaなければならないので、私は、グルーヴィーではないJavaからDSLを呼び出す:)

UPDATE 1:initalコメントと回答した後..

ので、スクリプトはGroovyShellによってDelegatingScriptとして評価されます。ここで、デリゲートはJavaオブジェクトです。クロージャーには、.propertiesファイルのプロパティが含まれています。これらのファイルは、異なるコンテキストで定義する必要があります。

env { 
    server-name=someHost1 
    database.name=someHost2 
    clientName=someHost3 
} 

委譲(Java)のオブジェクトが

public void env(Closure closure) { 
    Map map = new HashMap(); 
    closure.setDelegate(map); 
    closure.setResolveStrategy(Closure.DELEGATE_ONLY); 
    closure.call(); 
    ... do something with map... 

}

として、このブロックを読んでいました今、ユーザー(つまりいない私は)おそらく、スクリプトに元のプロパティファイルからコピーし、したがって、私はむしろタイプミスの原因になるので、あまり編集する必要はありません。

私が述べたように私は例3と6のコーブも持っています赤だけでなく、しかし、はい、ティムは、私はそれ暗黙のを忘れてしまった:)

今の私は、文字列にフォーマットを変更しているので、DSLは、マルチを使用して、ある

env ''' 
    server-name=someHost1 
    database.name=someHost2 
    clientName=someHost3 
''' 

のようなものを書き込み次いで-line代わりにクロージャの文字列、および文字列を読み取り、標準java.util.Properties使用:

public void env(String envString) { 
    Properties properties = new Properties; 
    properties.load(new StringReader(envString)) 
    ....etc 

}

、これは機能するがが、クロージャ及びmを有する混合極限線は今のところ唯一の欠点です。マップ宣言で

+0

あなたが説明することができます:「構文解析側がなければなりませんJava '? 内部Groovy DSLは、ここではマップ要素の割り当てのようなgroovy構文パーサー に依存しているので、Javaとどのように解析しますか? groovyと呼んでも、とにかくグルーヴィーサイドではこれはできませんか? – ARA

+0

'it.'exam-ple2 '= 123' –

答えて

0

、グルービーマップに例えばexample1などの識別子とexample2として文字列キーを解析:.with{}文脈において

[ example1: 1, example2: 2 ] 

、それはおそらくsetProperty(property, value)メカニズムを使用します。


しかし、あなたの場合は、式exam.pleexam-pleを備えています。これらの式は優先されるため、Groovyは最初にそれらを解決しようとします(恐らくexam.getProperty('ple')exam.minus(ple)など)。

あなたは、いくつかの構文上の選択肢を持っていますが、あなたはそれを明確に文字列キーことになっているものをGroovyのために加える必要がありますし、他の表現するものです。

def map = [ 
    'exam.ple4' : 4, // direct map declaration 
    example5 : 5 // unambiguous key declaration: no quotes needed 
] 

map.with { 
    example1 = 1 
    put 'exam.ple2', 2 // ambiguous, needs quotes 
    it.'exam-ple3' = 3 // as per @TimYates suggestion 
} 

assert map['exam-ple3'] == 3 
assert map.'exam.ple2' == 2 
assert map['exam.ple4'] == 4 
assert map.example5 == 5 // again, no quotes needed for key 
関連する問題