住所文字列のパースを確実に処理する方法

#住所パースバッチについて
総務省が出している自治体コードで住所文字列をパースする場合の実際にうまくいっている仕様と住所構造の説明しちゃいますよ！

##市長村23区マスタと行政区マスタ
ここでつかっているpref_cd、city_cdとward_cdは総務省が出している自治体コード

- 都道府県
 - 市町村23区レイヤー
  - 政令市の場合は行政区のレイヤー

という形で情報整理したいので

```
cityマスター
wardマスター
```

に分ける。

##日本の住所構造について
###都道府県
 日本国内最大の地方自治体です。
 もともと明治に東京・大阪・京都の３大重要都市を内包する県域に府をおいて重要視したなごりで、現在は権能上の差はありません。東京都のみは東京府と東京市が合併したため、東京市が本来になう東京特別区内の市役所的な業務も担当しています。また警視庁のみ他の道府県警より組織的に大きいこともあり、警視庁長官職の階級が上とか些細な違いはあります。北海道は行政範囲が広大であるため、道内に支庁を設けていますが住所上の影響はありません。

###郡
元は大化の改新あたりからの律令制への移行のながれで、煩雑だった国造国を統合し、旧国造国の小国は郡に大国はいくつかの郡に分割するなどし郡衙を置き、いくつかの郡をまとめて国を設置し、国は国府を接続する国道単位で行政区画を整理したなごりです。
 明治維新後に市町村制が発布された頃は現在の大字単位程度の村落レベルで村が存在していたため、各町村の財政基盤が貧弱でした。そのため市を除く広域行政を扱う自治体として、概ね律令制での郡の領域単位で、郡役所が置かれたなごりです。
 今日では住所だけな上に平成の大合併で町村そのものがなくなりかけていますので形骸化しています。
自治体コードなどはない住所以外では必要性がない概念です。
現在でも市に昇格すると郡が住所からなくなる制度は残っていますので、郡に従属するのは町村のみになります。
例：烏山町が合併で那須烏山市になった場合　栃木県那須郡烏山町→栃木県那須烏山市
 
### 市町村
 地方自治体もっとも基礎的な単位 一般的な市町村、市の番地としての稲荷町４丁目みたいな町は地域が稲荷町という地名なだけで自治体の町ではない。

### 東京23特別区
戦中に行政効率化と統制強化を目的として東京市と東京府を府市統合した結果誕生した、上位の自治体は都であって階層としては市町村と同じレイヤーです。

### 政令指定都市
 政令により定められる都道府県から各種の権限を大きく移譲される市。平成の大合併の時限立法により昇格要件が大幅に緩和され増えました。概ね人口80万人程度以上の都市が昇格しており、地域行政のために、人口10万から30〜40万人程度の行政区を内包しています。行政区も自治体としての法人格があります。
 県との関係が中途半端なのは戦後、大都市行政を特別行政区という単位で、県と並列な存在として設置する計画があったのですが、大都市を抱える都道府県が猛反発したためにお茶を濁した結果です。

###政令指定都市の行政区
東京23区とはことなり、政令指定都市に従属する自治体で地域行政を担当しています。
 
##パースバッチのルール

- 前方一致のindex 0または前方から最初に一致する文字列検索で解決していく方向でかためる
 - 以下の文章中で単に前方一致と書く場合は前方一致でindex0の場合とします。
- マスタードリブンが一番安全という認識

##神奈川県横浜市都筑区川和3-10-5を例にルーリングを解説
###前処理
- 半角・全角空白文字を処理対象文字列から削除する

###県のパース処理
```
- 都道府県マスターから前方一致でマッチング
  - 都道府県がマッチングする場合
    - pref_cdを上書きする
    - 都道府県の文字列を削除する
    - 市町村23区のパース処理へ
 - 都道府県がマッチングしない場合
    - pref_cdが設定済みか確認する
      - pref_cdが設定されている
        - 市町村23区のパース処理へ
      - pref_cdが設定されていない
        - 住所入力不備扱いで次のレコードの処理へ
```

###市町村23区のパース処理
この時点で処理対象文字列は

```
横浜市都筑区川和3-10-5
```
となっている

```
- 所在都道府県の市町村23区のリストをcityマスタから引いてくる
- 引いてきた市町村マスターから前方から最初に一致する文字列でマッチング
  - 市町村がマッチングした場合
    - 一致した箇所のindexが先頭文字かチェック
      - 先頭文字である
        - city_cdを上書きする
        - 政令市行政区パース処理へ移動  
      - 先頭文字でない
        - 前方から最初に見つかる郡を探す
          -  郡が存在する場合
             - 最初の郡までの文字列を削除する
             - 郡までを削除した文字列で処理中の市町村23区名が前方一致するかチェック
               - 一致する場合
                 - city_cdを上書きする
                 - 政令市行政区パース処理へ移動  
               - 一致しない場合
                 - 次の市町村23区とのマッチング処理を行う 
          - 郡が存在しない場合
            - マンション名などの可能性があるため次の市町村とマッチング処理を行う    
  - すべての市町村がマッチングしない
   - 対象レコードのパース処理終了、次のレコードへ
```

###政令市行政区のパース処理
この時点で処理対象文字列は

```
横浜市都筑区川和3-10-5
```
のまま

```
- 市町村区23区のcity_cdに紐づく行政区をwardマスタの中から引き出す
  - 行政区がない場合
    - 対象レコードのパース処理終了、次のレコードへ
- 引いてきたwardマスタから前方一致でマッチング
  - マッチングする場合
    - ward_cdを上書きする
    - 対象レコードのパース処理終了、次のレコードへ
  - すべてマッチングしない場合
    - 対象レコードのパース処理終了、次のレコードへ
```



##パターン別種類

###東京都渋谷区道玄坂
都道府県マスタから文字列先頭が東京都マッチングする。
都道府県コード特定:13
市町村マスタから文字列先頭から最初に一致するものでマッチングする。
渋谷区がindex0で引っかかる。

###東京都中央区
東京都中央区 
先ほどの渋谷区と同じ形でマッチングできる。

###中央区 pref_cd 13
中央区 pref_cd 13

pref_cd = 13なので
東京都の市町村区からマッチングできる

###渋谷区道玄坂 pref_cd null
都道府県が特定できないので、continueしちゃう。

###神奈川県横浜市都筑区港北
横浜市までは東京都渋谷区と同じ。
横浜市の行政区をひっぱります。
横浜市都築区をマッチングできます。

###日本,神奈川県横浜市都筑区港北 pref 14
pref codeで神奈川県の自治体から検索します。
横浜市でひっかかりますが。郡ではないので飛ばしちゃいます。
存在しない都道府県扱いでcontinueになります。

###横浜市都筑区港北 pref null
continuしちゃう。渋谷区道玄坂とpref nullと同じ
町村が重複するおそれありだから

###都筑区港北
continuしちゃう。

###神奈川県鎌倉市箱根町(自治体ではないが住所として町がつく場合)
実際にはない住所だが、同一県内の町名が市の住所名称として使われている場合
これは普通に前方から一致させるので問題なくパースして終了できる。

###鎌倉市中央
continuしちゃいます。

###神奈川県足柄郡箱根町元湯
県マッチングします。
前方から最初に一致する箱根町でマッチングされます。
最初の郡まで消しちゃいます。
箱根町元湯になります。
もう一度検索文字列でこんどは前方一致で検索します。
箱根町でマッチングできました。