ISBN, JAN。クラスライブラリ
半月ぶりに書きました。
ISBN-13 のチェックデジットを計算する感じの小物でも作ろうかと。
一先ずクラスライブラリだけ実装。
副産物として同じ計算式を使ってるJAN(EAN)13桁と短絡8桁や、
UPC、ITFの14桁と16桁なんかにも対応してます。
ペーパー・プロトタイピングを昨日、実装を今日に。
この前のは入門書的な1本ソースで書き上げてしまいましたが、
パッケージ分け、クラス分けはちゃんとした方が理解度が変わってきます。
違ってればちゃんとコンパイラが突っ込んで来ますから、成る程そーなのかーってなりますし。
パッケージ構成
./EanTest.java ./jp/regekatsu/utility/WpcAbstract.java ./jp/regekatsu/utility/Ean.java
./EanTest.java
/*--------------------------------------------------------------------------------- class EanTest version 0.01 May 20, 2012 by DumBo ---------------------------------------------------------------------------------*/ import jp.regekatsu.utility.Ean; class EanTest { public static void main(String[] args) { Ean jan8 = new Ean(Ean.CODE_JAN8); Ean jan13 = new Ean(Ean.CODE_JAN13); Ean isbn13 = new Ean(Ean.CODE_ISBN13); Ean upc = new Ean(Ean.CODE_UPC); Ean itf14 = new Ean(Ean.CODE_ITF14); Ean itf16 = new Ean(Ean.CODE_ITF16); jan8.setCode("4912345"); jan13.setCode("456995111617"); isbn13.setCode("978123456789"); upc.setCode("06141411234"); itf14.setCode("1490123456789"); itf16.setCode("010490123456789"); System.out.println("JANコード(短絡タイプ8桁) : " + jan8.getCode() + jan8.getCheckDigit()); System.out.println("JANコード(標準タイプ13桁) : " + jan13.getCode() + jan13.getCheckDigit()); System.out.println("ISBNコード(現行規格13桁) : " + isbn13.getCode() + isbn13.getCheckDigit()); System.out.println("UPCコード(12桁) : " + upc.getCode() + upc.getCheckDigit()); System.out.println("ITF-14コード(14桁) : " + itf14.getCode() + itf14.getCheckDigit()); System.out.println("ITF-16コード(16桁) : " + itf16.getCode() + itf16.getCheckDigit()); } }
./jp/regekatsu/utility/WpcAbstract.java
/*--------------------------------------------------------------------------------- abstract class WpcAbstract version 0.01 May 20, 2012 by DumBo ---------------------------------------------------------------------------------*/ package jp.regekatsu.utility; abstract class WpcAbstract { int codeSize; String code; abstract int getCodeSize(); abstract String getCode(); abstract void setCode(String code); abstract String getCheckDigit(); }
./jp/regekatsu/utility/Ean.java
/*--------------------------------------------------------------------------------- class Ean extends WpcAbstract version 0.01 May 20, 2012 by DumBo ---------------------------------------------------------------------------------*/ package jp.regekatsu.utility; public class Ean extends WpcAbstract { public static final int CODE_EAN8 = 7; public static final int CODE_JAN8 = CODE_EAN8; public static final int CODE_EAN13 = 12; public static final int CODE_JAN13 = CODE_EAN13; public static final int CODE_ISBN13 = CODE_EAN13; public static final int CODE_UPC = 11; public static final int CODE_ITF14 = 13; public static final int CODE_ITF16 = 15; static final int MODULUS = 10; static final int WAIT = 3; public Ean(int codeSize) { //コード桁数が0以下でないか確認する if(codeSize <= 0) throw new IllegalArgumentException("コード桁数は最低でも0より大きい数を指定してください。"); this.codeSize = codeSize; String code = ""; for(int i = 0;i < this.codeSize;i++) code += "0"; this.code = code; } public int getCodeSize() { return codeSize; } public String getCode() { return code; } public void setCode(String code) { //コード桁数が設定値と一致してるか確認する。 if(code.length() != codeSize) throw new IllegalArgumentException("設定した桁数と引数の桁が一致しません。"); //コードが数字のみで構成されてるか確認する。 String isNumber = "[0-9]{" + String.valueOf(codeSize) + "}"; if(code.matches(isNumber) != true) throw new IllegalArgumentException("指定したコードに数字以外の文字が含まれてます。"); this.code = code; } public String getCheckDigit() { /* 計算方法 1.奇数桁を全て合計して×1で総計を求める。 2.偶数桁を全て合計して×3で総計を求める。 3.奇数桁総計と偶数桁総計を足した数から÷10で余りを求める。 4.10から余りを引くことでチェックデジットが求められる。 ※この計算方法はJAN13桁、ISBN13桁に限らず JAN短絡8桁、UPC12桁、ITF14、16桁も、 同一手順でもってチェックデジットを求めることが出来る。 */ /* コード桁数 + チェックデジット1桁 = 総桁数 が 偶数なら文字列の偶数要素数(0,2,4,...)は偶数桁、 奇数なら文字列の偶数要素数(0,2,4,...)が奇数桁となる。 例) EAN(コード12桁 + チェックデジット1桁) 桁数 13 12 11 10 09 08 07 06 05 04 03 02 01 偶奇 奇 偶 奇 偶 奇 偶 奇 偶 奇 偶 奇 偶 奇 要素数 [00][01][02][03][04][05][06][07][08][09][10][11] + [12] UPC(コード11桁 + チェックデジット1桁) 桁数 12 11 10 09 08 07 06 05 04 03 02 01 偶奇 偶 奇 偶 奇 偶 奇 偶 奇 偶 奇 偶 奇 要素数 [00][01][02][03][04][05][06][07][08][09][10] + [11] 総桁数が奇数の場合は最初の要素を奇数として、 また逆に偶数の場合は最初の要素を偶数として扱い、1つ飛ばしで計算する為に、 コード桁数 % 2 = 奇数桁の入った要素の始点、 (コード桁数 + チェックデジット1桁) % 2 = 偶数桁の入った要素の始点、 として扱っている。 */ //奇数桁の計算 int odd = 0; for(int i = codeSize % 2;i < codeSize;i += 2) odd += Integer.parseInt(code.substring(i, i + 1)); //偶数桁の計算 int even = 0; for(int i = (codeSize + 1) % 2;i < codeSize;i += 2) even += Integer.parseInt(code.substring(i, i + 1)); even *= WAIT; //結果の計算 int temporaryDigit = MODULUS - ((odd + even) % MODULUS); return String.valueOf(temporaryDigit); } }