AndroidでJEXLを使う
Androidで使えるクエリ言語ってなかなか見つからないものです。
javax.scriptはAndroidでは使えないし。。
そんなところでこんな記事を見つけて、Java Expression Language (JEXL)を試してみました。
ソースコード azyobuzin/JexlSample · GitHub
今回は http://commons.apache.org/jexl/ にならって、コレクションにEnumerable.Whereをかけるようなのを作ってみました。
//txtQuery - クエリ入力欄 //sourcePreview - コレクションのプレビュー用ListView //省略 private void run() { try { String query = txtQuery.getText().toString(); if (query.isEmpty()) return; //エンジンの作成・式の組立 JexlEngine engine = new JexlEngine(); Expression expr = engine.createExpression(query); ListAdapter adapter = sourcePreview.getAdapter(); ArrayList<Object> resultItems = new ArrayList<Object>(); for (int i = 0; i < adapter.getCount(); i++) { Object item = adapter.getItem(i); //変数を挿入 JexlContext ctx = new MapContext(); ctx.set("item", item); //実行! Object result = expr.evaluate(ctx); if (result instanceof Boolean) { if ((Boolean)result) resultItems.add(item); } else { new AlertDialog.Builder(this) .setTitle(R.string.result) .setIcon(android.R.drawable.ic_dialog_alert) .setMessage(R.string.result_is_not_boolean) .setPositiveButton(android.R.string.ok, emptyListener) .show(); return; } } String resultString = ""; for (Object item : resultItems) { resultString += item.toString() + "\n"; } new AlertDialog.Builder(this) .setTitle(R.string.result) .setIcon(android.R.drawable.ic_dialog_info) .setMessage(resultString) .setPositiveButton(android.R.string.ok, emptyListener) .show(); } catch (Exception ex) { new AlertDialog.Builder(this) .setTitle(R.string.result) .setIcon(android.R.drawable.ic_dialog_alert) .setMessage(ex.getClass().getName() + "\n\n" + ex.getMessage()) .setPositiveButton(android.R.string.ok, emptyListener) .show(); } } //省略
createExpressionで文法が間違っているときに、evaluateで実行に失敗したときに例外を吐かれるので、落ちない保証がないときはcatchしてあげましょう。
はい、ちゃんと動きました。
で、これの使い道ですが、ラムダ式として使えればなぁとか考えてたり。あと、Twitterクライアントの振り分けとかに使いたいです。そこまで作れるかが問題ですが。。