2017-06-16 1 views
0

私はカスタムFreeMarkerディレクティブを作成しています。私の実装の一環として、executeメソッド内のカスタムディレクティブのBodyにアクセスしたいと思います。 TemplateDirectiveBody本体またはEnvironment envから取得する方法はありますか?私はポイントがあなたのことであると仮定しFreeMarker:TemplateDirectiveModelの実装中にTemplateDirectiveBodyを文字列として取得するにはどうすればよいですか?

Writer w = new StringWriter(); 
env.getCurrentTemplate().dump(w); 

答えて

0

:私はのようなものを使用することにより、完全なテンプレート文字列を望んでいないテンプレート

<@loop>My name is ${name}</@loop> 

実装

public class LoopDirective implements TemplateDirectiveModel{ 
    public LoopDirective() { 
    } 
    public void execute(Environment env, 
     Map params, TemplateModel[] loopVars, 
     TemplateDirectiveBody body) 
     throws TemplateException, IOException { 
     System.out.println(body); 
     // I want to print "My name is ${name}" 
    } 
} 

使い方${name}を解決したくない場合は(TemplateDirectiveBody API)。あなたはそれをすることができないはずです。しかし、私はあなたが汚れたトリックを引くことができると思う、源の位置をenv.getCurrentDirectiveCallPlace()から得ることによって。今では元のソースコードのどの部分を切り捨てる必要があるのか​​分かりますが、区切りタグが含まれているので、独自のプログラムロジックでそれらを削除する必要があります(単純な構文解析のビット...)。理論的には、テンプレートのソースコードを取得している時点で、Templateオブジェクトにはそのようなものはありません。しかし、いくつかの悪い遺産のおかげで、あなたはTemplate.getSource(int, int, int, int)を手に入れました。しかし、ConfigurationtabSizeを1に設定しない限り、タブはスペースで置き換えられます。知るべきもう一つのことは、Template.getSourceがやや遅い(メモリ内の文字をいくらか無駄にコピーする)、毎回区切りタグを削除する必要があるということです。しかし、スピードの問題は、DirectiveCallPlace.getOrCreateCustomDataを使用して回避することもできます。これにより、コールの最後にStringをキャッシュできます。

+0

ありがとうございます。はい、私は '$ {name} 'を解決したくありません。 「あなたはそれをすることができないはずです」と言いますと、何らかの理由がありますか? また、[getChildrenBuffer](https://github.com/apache/incubator-freemarker/blob/2.3-gae/src/main/java/freemarker/core/Environment.java#L2807)がここで公開されていないのでしょうか? Template.getSource(int、int、int、int)は私を助けません。私がカスタムディレクティブを使ってやろうとしていることは、ネストを避けることですが、繰り返しが可能です。 有効 <@loop> $ {ABC}<@loop> $ {XYZ} <@loop>無効$ {ABC} <@loop> $ {XYZ}

+0

さて、あなたは値を代入するテンプレート言語を指示した場合、それはむしろですその動作を抑止するのに珍しいことであり、(文書化された動作を変更したので)テンプレートを読んだ人には混乱します。しかし、私はあなたが達成したいことを理解していません。実行時にグローバル変数をチェックして、 'loop'を' loop'にネストすることを禁止することができます。それはなぜ$ {exp} 'を解決しないことに関連していますか? AST API-s、特に'getChildrenBuffer'は、実装レベルの低い実装です。 – ddekany

+0

返信いただきありがとうございます。実行時にグローバル変数をチェックしながら 'loop'を' loop'に入れ子にすることをどうやって禁止できますか? 私たちはユーザーからのテンプレートを受け入れています。無限ループやあまりにも多くの繰り返しを避けたいというセキュリティのためです。ループの最大反復回数を制御することができる '#list'のようなカスタムループ指令「<@loop>」を作成しており、ネストを制限することもできます。つまり、「<@loop><@loop><@/loop>」です。しかし、 '<@loop><@loop>'のような繰り返しが必要です。 –

関連する問題