このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
次は上へ・下へボタンの処理だ。
これもインデックスを使っての操作となるが、
削除のように簡単にはいかない。
ちょっとしたアルゴリズムとも言えるかも。
これはインデックスを使って入れ替えが必要なので、
昨日と同じように、インデックスのずれにも注意が必要だ。
上に動かす場合を例として、方針を練ってみよう。
基本は、選択したものをそのまま 1 つ上にずらすのだが、
飛び飛びに選択した状態で上に移動したとしても、
飛び飛びの状態をそのまま保つように移動させることにする。
例えば、A B C D E というルールがあり、
B と D を上に移動すると、B A D C E となる。
この状態でさらに B と D を選択して上に移動しても、
B と D の位置関係を保つため、変化させない。
つまり、D と A は入れ替えないことにする。
こういう風に設計しておけば、以下のような仮定ができる。
1. チェックされたルールはすべて移動するか、
すべて移動しないかのどちらかである。
2. 最も下が選択された場合、下への移動はできない。
最も上が選択された場合、上への移動はできない。
こうすると実装に関して少し楽ができるのだ。
移動可能か不可能かは、端の要素が選択されてるかで判断し、
可能であれば、すべてのインデックスに対して、
その上(または下)の要素と入れ替えるという処理となる。
この入れ替えは、削除の時と同じく、順序が大事だ。
上に移動する場合は、上の要素から順番に入れ替えないと、
誤って選択された要素同士を入れ替える危険性がある。
⇒これは、昇順に並べ替えることで対処しよう。
また、インデックスで処理を行う場合、
同じインデックスが複数含まれると困ったことになる。
そのため、選択された番号が一意であるか調べる必要がある。
これは、律儀に調べてもいいが、Set を使う手もある。
Set インタフェースは、要素の重複を許さないからだ。
では、この方針に従って、上への移動を実装してみよう。
========== ManageRulesAction#moveUp ==========
public ActionForward moveUp(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
// フォームを取得
ManageFilterRulesForm manageForm =
(ManageFilterRulesForm)form;
// 選択されたルール番号を取得
int[] selected = manageForm.getSelected();
if (selected != null && selected.length > 0) {
// 重複を省き、かつ昇順に並べる
SortedSet<Integer> indexes =
new TreeSet<Integer>();
for (int index : selected) {
indexes.add(index); // ボックス化
}
// 現在のフィルタ設定を読み込む
Filter filter = FilterManager.load();
List<FilterRule> rules = filter.getRules();
// 最初のルールが選択されていたら動かせない
if (indexes.first() > 0) {
// 前から順に上と交換
for (int index : indexes) {
FilterRule rule = rules.get(index);
rules.set(index, rules
.get(index - 1));
rules.set(index - 1, rule);
}
// 保存する
FilterManager.save(filter);
}
}
// OK
return mapping
.findForward(Forwards.SUCCESS_KEY);
}
========== end of ManageRulesAction#moveUp ==========
Set<T> を使うには、要素をオブジェクトにする必要がある。
なので、int である要素番号は Integer にボックス化する。
Java では、配列を一気にボックス化できないので、
地道に各要素を列挙して格納する。
どうせ並び替えをしなければならないのであれば、
順番の規定も行う SortedSet 実装の TreeSet を使おう。
最後に、SortedSet を拡張 for 構文で列挙。
TreeSet の保障により、確実に一意の値が昇順に返される。
あとはこのインデックスを使って要素の入れ替えを行う。
しかし処理速度は遅そうだ。コードが読みやすいので良いけど。