前回までで、3-way-merge が実装できました。
今回は、記載できなかった小さなテクニックを2つお話しします。
deltas の一部をapplyTo() として適用する方法
前回 (2) の時に試した通りdiff() メソッドの戻り値から、差分の一覧を取得できます。
val patch = DiffUtils.diff(base, local)
patch.detlas <-- List型の差分
この差分を全てではなく一部のみを、applyTo するやり方があります。
// 差分の一部を抜き出し
val newDeltas = listOf(patch.deltas[3], patch.deltas[5], …)
// Patch オブジェクトを新規作成
val patch = Patch()
// 抜き出した差分を登録
patch.deltas.addAll(deltas)
// 元文章にパッチを適用
val applied = patch.applyTo(base)
このように新たにPatch を作成してそこにdelta を登録することでapplyTo が使えます。
ただし、delta は修正対象を行番号で管理しているため、base を変更すると整合性が合わなくなりエラーになになる点は注意する必要があります。
差分が適用された範囲を抜き出す方法
元の文章 (base)
A B C D E F G
修正後の文章 (local)
A B x D x F G
ここから、差分を適用して x D x を抽出するには、下の手順が必要です。
- 元文章から範囲の後半部分を削除
A B C D E F G からF Gを削除します
–> A B C D E - applyTo を使用して差分を適用
後半部分(F G)に差分はないので問題なく適用できます
–> A B x D x - 適用後の文章から前半部分を削除
A B x D x からA B を削除
–> x D x
こうすることで、整合性を合わせつつ、修正後の文字列が取得できます。
はじめに後半を削除しないと、2. でINSERT が行われた場合、後半部分が何文字目から始まるのか算出するのが困難になります。
また、先に前半を削除すると、source.position が合わなくなり、applyTo でエラーが起きてしまいます。

